Merge official-stockfish/master
authorFabian Fichter <ianfab@users.noreply.github.com>
Sun, 31 Mar 2019 11:11:19 +0000 (13:11 +0200)
committerFabian Fichter <ianfab@users.noreply.github.com>
Sun, 31 Mar 2019 11:11:19 +0000 (13:11 +0200)
No functional change.

13 files changed:
1  2 
src/bitbase.cpp
src/bitboard.cpp
src/bitboard.h
src/endgame.cpp
src/evaluate.cpp
src/material.cpp
src/pawns.cpp
src/position.cpp
src/position.h
src/search.cpp
src/thread.cpp
src/timeman.cpp
src/ucioption.cpp

diff --cc src/bitbase.cpp
Simple merge
@@@ -375,247 -90,41 +375,247 @@@ void Bitboards::init() 
                DistanceRingBB[s1][SquareDistance[s1][s2]] |= s2;
            }
  
 -  int steps[][5] = { {}, { 7, 9 }, { 6, 10, 15, 17 }, {}, {}, {}, { 1, 7, 8, 9 } };
 +  // Piece moves
 +  Direction RookDirections[5] = { NORTH,  EAST,  SOUTH,  WEST };
 +  Direction BishopDirections[5] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST };
 +
 +#ifdef PRECOMPUTED_MAGICS
 +  init_magics(RookTable, RookMagics, RookDirections, RookMagicInit);
 +  init_magics(BishopTable, BishopMagics, BishopDirections, BishopMagicInit);
 +#else
 +  init_magics(RookTable, RookMagics, RookDirections);
 +  init_magics(BishopTable, BishopMagics, BishopDirections);
 +#endif
 +
 +  int stepsCapture[][13] = {
 +      {}, // NO_PIECE_TYPE
 +      { NORTH_WEST, NORTH_EAST }, // pawn
 +      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
 +        NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // knight
 +      {}, // bishop
 +      {}, // rook
 +      {}, // queen
 +      { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST }, // fers/met
 +      { 2 * SOUTH_WEST, 2 * SOUTH_EAST, 2 * NORTH_WEST, 2 * NORTH_EAST }, // alfil
 +      { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH, NORTH_EAST }, // silver/khon
 +      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH_WEST, SOUTH_EAST, SOUTH + 2 * EAST,
 +        NORTH + 2 * WEST, NORTH_WEST, NORTH_EAST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // aiwok
 +      { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST }, // bers/dragon
 +      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
 +        NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // archbishop
 +      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
 +        NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // chancellor
 +      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
 +        NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // amazon
 +      {}, // knibis
 +      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
 +        NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // biskni
 +      { NORTH }, // shogi pawn
 +      {}, // lance
 +      {  2 * NORTH + WEST, 2 * NORTH + EAST }, // shogi knight
 +      { WEST, EAST,  2 * NORTH + WEST, 2 * NORTH + EAST }, // euroshogi knight
 +      { SOUTH, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST }, // gold
 +      { SOUTH, WEST, EAST, NORTH }, // horse
 +      { SOUTH, WEST, EAST, NORTH }, // clobber
 +      { NORTH_WEST, NORTH_EAST }, // breakthrough
 +      {}, // immobile
 +      { SOUTH, WEST, EAST, NORTH }, // wazir
 +      { SOUTH_WEST, SOUTH, SOUTH_EAST, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST }, // commoner
 +      { SOUTH_WEST, SOUTH, SOUTH_EAST, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST } // king
 +  };
 +  int stepsQuiet[][13] = {
 +      {}, // NO_PIECE_TYPE
 +      { NORTH }, // pawn
 +      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
 +        NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // knight
 +      {}, // bishop
 +      {}, // rook
 +      {}, // queen
 +      { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST }, // fers/met
 +      { 2 * SOUTH_WEST, 2 * SOUTH_EAST, 2 * NORTH_WEST, 2 * NORTH_EAST }, // alfil
 +      { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH, NORTH_EAST }, // silver/khon
 +      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH_WEST, SOUTH_EAST, SOUTH + 2 * EAST,
 +        NORTH + 2 * WEST, NORTH_WEST, NORTH_EAST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // aiwok
 +      { SOUTH_WEST, SOUTH_EAST, NORTH_WEST, NORTH_EAST }, // bers/dragon
 +      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
 +        NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // archbishop
 +      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
 +        NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // chancellor
 +      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
 +        NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // amazon
 +      { 2 * SOUTH + WEST, 2 * SOUTH + EAST, SOUTH + 2 * WEST, SOUTH + 2 * EAST,
 +        NORTH + 2 * WEST, NORTH + 2 * EAST, 2 * NORTH + WEST, 2 * NORTH + EAST }, // knibis
 +      {}, // biskni
 +      { NORTH }, // shogi pawn
 +      {}, // lance
 +      {  2 * NORTH + WEST, 2 * NORTH + EAST }, // shogi knight
 +      { WEST, EAST,  2 * NORTH + WEST, 2 * NORTH + EAST }, // euroshogi knight
 +      { SOUTH, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST }, // gold
 +      { SOUTH, WEST, EAST, NORTH }, // horse
 +      {}, // clobber
 +      { NORTH_WEST, NORTH, NORTH_EAST }, // breakthrough
 +      {}, // immobile
 +      { SOUTH, WEST, EAST, NORTH }, // wazir
 +      { SOUTH_WEST, SOUTH, SOUTH_EAST, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST }, // commoner
 +      { SOUTH_WEST, SOUTH, SOUTH_EAST, WEST, EAST, NORTH_WEST, NORTH, NORTH_EAST } // king
 +  };
 +  Direction sliderCapture[][9] = {
 +    {}, // NO_PIECE_TYPE
 +    {}, // pawn
 +    {}, // knight
 +    { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // bishop
 +    { NORTH,  EAST,  SOUTH,  WEST }, // rook
 +    { NORTH,  EAST,  SOUTH,  WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // queen
 +    {}, // fers/met
 +    {}, // alfil
 +    {}, // silver/khon
 +    { NORTH,  EAST,  SOUTH,  WEST }, // aiwok
 +    { NORTH,  EAST,  SOUTH,  WEST }, // bers/dragon
 +    { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // archbishop
 +    { NORTH,  EAST,  SOUTH,  WEST }, // chancellor
 +    { NORTH,  EAST,  SOUTH,  WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // amazon
 +    { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // knibis
 +    {}, // biskni
 +    {}, // shogi pawn
 +    { NORTH }, // lance
 +    {}, // shogi knight
 +    {}, // euroshogi knight
 +    {}, // gold
 +    { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // horse
 +    {}, // clobber
 +    {}, // breakthrough
 +    {}, // immobile
 +    {}, // wazir
 +    {}, // commoner
 +    {} // king
 +  };
 +  Direction sliderQuiet[][9] = {
 +    {}, // NO_PIECE_TYPE
 +    {}, // pawn
 +    {}, // knight
 +    { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // bishop
 +    { NORTH,  EAST,  SOUTH,  WEST }, // rook
 +    { NORTH,  EAST,  SOUTH,  WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // queen
 +    {}, // fers/met
 +    {}, // alfil
 +    {}, // silver/khon
 +    { NORTH,  EAST,  SOUTH,  WEST }, // aiwok
 +    { NORTH,  EAST,  SOUTH,  WEST }, // bers/dragon
 +    { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // archbishop
 +    { NORTH,  EAST,  SOUTH,  WEST }, // chancellor
 +    { NORTH,  EAST,  SOUTH,  WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // amazon
 +    {}, // knibis
 +    { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // biskni
 +    {}, // shogi pawn
 +    { NORTH }, // lance
 +    {}, // shogi knight
 +    {}, // euroshogi knight
 +    {}, // gold
 +    { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }, // horse
 +    {}, // clobber
 +    {}, // breakthrough
 +    {}, // immobile
 +    {}, // wazir
 +    {}, // commoner
 +    {} // king
 +  };
 +  int sliderDistCapture[] = {
 +    0, // NO_PIECE_TYPE
 +    0, // pawn
 +    0, // knight
 +    FILE_MAX, // bishop
 +    FILE_MAX, // rook
 +    FILE_MAX, // queen
 +    0, // fers/met
 +    0, // alfil
 +    0, // silver/khon
 +    FILE_MAX, // aiwok
 +    FILE_MAX, // bers/dragon
 +    FILE_MAX, // archbishop
 +    FILE_MAX, // chancellor
 +    FILE_MAX, // amazon
 +    FILE_MAX, // knibis
 +    0, // biskni
 +    0, // shogi pawn
 +    FILE_MAX, // lance
 +    0, // shogi knight
 +    0, // euroshogi knight
 +    0, // gold
 +    FILE_MAX, // horse
 +    0, // clobber
 +    0, // breakthrough
 +    0, // immobile
 +    0, // wazir
 +    0, // commoner
 +    0  // king
 +  };
 +  int sliderDistQuiet[] = {
 +    0, // NO_PIECE_TYPE
 +    0, // pawn
 +    0, // knight
 +    FILE_MAX, // bishop
 +    FILE_MAX, // rook
 +    FILE_MAX, // queen
 +    0, // fers/met
 +    0, // alfil
 +    0, // silver/khon
 +    FILE_MAX, // aiwok
 +    FILE_MAX, // bers/dragon
 +    FILE_MAX, // archbishop
 +    FILE_MAX, // chancellor
 +    FILE_MAX, // amazon
 +    0, // knibis
 +    FILE_MAX, // biskni
 +    0, // shogi pawn
 +    FILE_MAX, // lance
 +    0, // shogi knight
 +    0, // euroshogi knight
 +    0, // gold
 +    FILE_MAX, // horse
 +    0, // clobber
 +    0, // breakthrough
 +    0, // immobile
 +    0, // wazir
 +    0, // commoner
 +    0  // king
 +  };
  
    for (Color c = WHITE; c <= BLACK; ++c)
 -      for (PieceType pt : { PAWN, KNIGHT, KING })
 -          for (Square s = SQ_A1; s <= SQ_H8; ++s)
 -              for (int i = 0; steps[pt][i]; ++i)
 +      for (PieceType pt = PAWN; pt <= KING; ++pt)
 +          for (Square s = SQ_A1; s <= SQ_MAX; ++s)
 +          {
 +              for (int i = 0; stepsCapture[pt][i]; ++i)
                {
 -                  Square to = s + Direction(c == WHITE ? steps[pt][i] : -steps[pt][i]);
 +                  Square to = s + Direction(c == WHITE ? stepsCapture[pt][i] : -stepsCapture[pt][i]);
  
 -                  if (is_ok(to) && distance(s, to) < 3)
 +                  if (is_ok(to) && distance(s, to) < 4)
                    {
 -                      if (pt == PAWN)
 -                          PawnAttacks[c][s] |= to;
 -                      else
 -                          PseudoAttacks[pt][s] |= to;
 +                      PseudoAttacks[c][pt][s] |= to;
 +                      LeaperAttacks[c][pt][s] |= to;
                    }
                }
 +              for (int i = 0; stepsQuiet[pt][i]; ++i)
 +              {
 +                  Square to = s + Direction(c == WHITE ? stepsQuiet[pt][i] : -stepsQuiet[pt][i]);
  
 -  Direction RookDirections[] = { NORTH, EAST, SOUTH, WEST };
 -  Direction BishopDirections[] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST };
 -
 -  init_magics(RookTable, RookMagics, RookDirections);
 -  init_magics(BishopTable, BishopMagics, BishopDirections);
 +                  if (is_ok(to) && distance(s, to) < 4)
 +                  {
 +                      PseudoMoves[c][pt][s] |= to;
 +                      LeaperMoves[c][pt][s] |= to;
 +                  }
 +              }
 +              PseudoAttacks[c][pt][s] |= sliding_attack(sliderCapture[pt], s, 0, sliderDistCapture[pt], c);
 +              PseudoMoves[c][pt][s] |= sliding_attack(sliderQuiet[pt], s, 0, sliderDistQuiet[pt], c);
 +          }
  
 -  for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
 +  for (Square s1 = SQ_A1; s1 <= SQ_MAX; ++s1)
    {
 -      PseudoAttacks[QUEEN][s1]  = PseudoAttacks[BISHOP][s1] = attacks_bb<BISHOP>(s1, 0);
 -      PseudoAttacks[QUEEN][s1] |= PseudoAttacks[  ROOK][s1] = attacks_bb<  ROOK>(s1, 0);
 -
        for (PieceType pt : { BISHOP, ROOK })
 -          for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
 -              if (PseudoAttacks[pt][s1] & s2)
 +          for (Square s2 = SQ_A1; s2 <= SQ_MAX; ++s2)
 +              if (PseudoAttacks[WHITE][pt][s1] & s2)
                {
 -                  LineBB[s1][s2] = (attacks_bb(pt, s1, 0) & attacks_bb(pt, s2, 0)) | s1 | s2;
 -                  BetweenBB[s1][s2] = attacks_bb(pt, s1, square_bb(s2)) & attacks_bb(pt, s2, square_bb(s1));
 +                  LineBB[s1][s2] = (attacks_bb(WHITE, pt, s1, 0) & attacks_bb(WHITE, pt, s2, 0)) | s1 | s2;
-                   BetweenBB[s1][s2] = attacks_bb(WHITE, pt, s1, SquareBB[s2]) & attacks_bb(WHITE, pt, s2, SquareBB[s1]);
++                  BetweenBB[s1][s2] = attacks_bb(WHITE, pt, s1, square_bb(s2)) & attacks_bb(WHITE, pt, s2, square_bb(s1));
                }
    }
  }
diff --cc src/bitboard.h
@@@ -139,41 -106,17 +139,19 @@@ extern Magic BishopMagics[SQUARE_NB]
  /// Overloads of bitwise operators between a Bitboard and a Square for testing
  /// whether a given bit is set in a bitboard, and for setting and clearing bits.
  
- inline Bitboard operator&(Bitboard b, Square s) {
+ inline Bitboard square_bb(Square s) {
 -  assert(s >= SQ_A1 && s <= SQ_H8);
 +  assert(s >= SQ_A1 && s <= SQ_MAX);
-   return b & SquareBB[s];
+   return SquareBB[s];
  }
+   
+ inline Bitboard  operator&( Bitboard  b, Square s) { return b &  square_bb(s); }
+ inline Bitboard  operator|( Bitboard  b, Square s) { return b |  square_bb(s); }
+ inline Bitboard  operator^( Bitboard  b, Square s) { return b ^  square_bb(s); }
+ inline Bitboard& operator|=(Bitboard& b, Square s) { return b |= square_bb(s); }
+ inline Bitboard& operator^=(Bitboard& b, Square s) { return b ^= square_bb(s); }
  
- inline Bitboard operator|(Bitboard b, Square s) {
-   assert(s >= SQ_A1 && s <= SQ_MAX);
-   return b | SquareBB[s];
- }
- inline Bitboard operator^(Bitboard b, Square s) {
-   assert(s >= SQ_A1 && s <= SQ_MAX);
-   return b ^ SquareBB[s];
- }
- inline Bitboard operator-(Bitboard b, Square s) {
-   assert(s >= SQ_A1 && s <= SQ_MAX);
-   return b & ~SquareBB[s];
- }
- inline Bitboard& operator|=(Bitboard& b, Square s) {
-   assert(s >= SQ_A1 && s <= SQ_MAX);
-   return b |= SquareBB[s];
- }
- inline Bitboard& operator^=(Bitboard& b, Square s) {
-   assert(s >= SQ_A1 && s <= SQ_MAX);
-   return b ^= SquareBB[s];
- }
- inline Bitboard& operator-=(Bitboard& b, Square s) {
-   assert(s >= SQ_A1 && s <= SQ_MAX);
-   return b &= ~SquareBB[s];
- }
++inline Bitboard& operator-=(Bitboard& b, Square s) { return b &= ~square_bb(s); }
 +
  constexpr bool more_than_one(Bitboard b) {
    return b & (b - 1);
  }
diff --cc src/endgame.cpp
Simple merge
Simple merge
@@@ -139,102 -129,79 +138,102 @@@ Entry* probe(const Position& pos) 
  
    Value npm_w = pos.non_pawn_material(WHITE);
    Value npm_b = pos.non_pawn_material(BLACK);
-   Value npm = std::max(EndgameLimit, std::min(npm_w + npm_b, MidgameLimit));
+   Value npm   = clamp(npm_w + npm_b, EndgameLimit, MidgameLimit);
  
    // Map total non-pawn material into [PHASE_ENDGAME, PHASE_MIDGAME]
 -  e->gamePhase = Phase(((npm - EndgameLimit) * PHASE_MIDGAME) / (MidgameLimit - EndgameLimit));
 -
 -  // Let's look if we have a specialized evaluation function for this particular
 -  // material configuration. Firstly we look for a fixed configuration one, then
 -  // for a generic one if the previous search failed.
 -  if ((e->evaluationFunction = pos.this_thread()->endgames.probe<Value>(key)) != nullptr)
 -      return e;
 -
 -  for (Color c = WHITE; c <= BLACK; ++c)
 -      if (is_KXK(pos, c))
 -      {
 -          e->evaluationFunction = &EvaluateKXK[c];
 -          return e;
 -      }
 -
 -  // OK, we didn't find any special evaluation function for the current material
 -  // configuration. Is there a suitable specialized scaling function?
 -  const EndgameBase<ScaleFactor>* sf;
 -
 -  if ((sf = pos.this_thread()->endgames.probe<ScaleFactor>(key)) != nullptr)
 +  if (pos.captures_to_hand())
    {
 -      e->scalingFunction[sf->strongSide] = sf; // Only strong color assigned
 -      return e;
 +      npm = VALUE_ZERO;
 +      for (PieceType pt : pos.piece_types())
 +          npm += (pos.count_in_hand(WHITE, pt) + pos.count_in_hand(BLACK, pt)) * PieceValue[MG][make_piece(WHITE, pt)];
 +      e->gamePhase = Phase(PHASE_MIDGAME * (MidgameLimit - std::min(npm, MidgameLimit)) / MidgameLimit);
    }
 -
 -  // We didn't find any specialized scaling function, so fall back on generic
 -  // ones that refer to more than one material distribution. Note that in this
 -  // case we don't return after setting the function.
 -  for (Color c = WHITE; c <= BLACK; ++c)
 +  else
 +      e->gamePhase = Phase(((npm - EndgameLimit) * PHASE_MIDGAME) / (MidgameLimit - EndgameLimit));
 +
 +#ifdef LARGEBOARDS
 +  // Disable endgame evaluation until it works independent of board size
 +  if (false)
 +#else
 +  if (pos.endgame_eval())
 +#endif
    {
 -    if (is_KBPsK(pos, c))
 -        e->scalingFunction[c] = &ScaleKBPsK[c];
 -
 -    else if (is_KQKRPs(pos, c))
 -        e->scalingFunction[c] = &ScaleKQKRPs[c];
 -  }
 +      // Let's look if we have a specialized evaluation function for this particular
 +      // material configuration. Firstly we look for a fixed configuration one, then
 +      // for a generic one if the previous search failed.
 +      if ((e->evaluationFunction = pos.this_thread()->endgames.probe<Value>(key)) != nullptr)
 +          return e;
  
 -  if (npm_w + npm_b == VALUE_ZERO && pos.pieces(PAWN)) // Only pawns on the board
 -  {
 -      if (!pos.count<PAWN>(BLACK))
 +      for (Color c = WHITE; c <= BLACK; ++c)
 +          if (is_KFsPsK(pos, c))
 +          {
 +              e->evaluationFunction = &EvaluateKFsPsK[c];
 +              return e;
 +          }
 +
 +      for (Color c = WHITE; c <= BLACK; ++c)
 +          if (is_KXK(pos, c))
 +          {
 +              e->evaluationFunction = &EvaluateKXK[c];
 +              return e;
 +          }
 +
 +      // OK, we didn't find any special evaluation function for the current material
 +      // configuration. Is there a suitable specialized scaling function?
 +      const EndgameBase<ScaleFactor>* sf;
 +
 +      if ((sf = pos.this_thread()->endgames.probe<ScaleFactor>(key)) != nullptr)
        {
 -          assert(pos.count<PAWN>(WHITE) >= 2);
 -
 -          e->scalingFunction[WHITE] = &ScaleKPsK[WHITE];
 +          e->scalingFunction[sf->strongSide] = sf; // Only strong color assigned
 +          return e;
        }
 -      else if (!pos.count<PAWN>(WHITE))
 +
 +      // We didn't find any specialized scaling function, so fall back on generic
 +      // ones that refer to more than one material distribution. Note that in this
 +      // case we don't return after setting the function.
 +      for (Color c = WHITE; c <= BLACK; ++c)
        {
 -          assert(pos.count<PAWN>(BLACK) >= 2);
 +        if (is_KBPsK(pos, c))
 +            e->scalingFunction[c] = &ScaleKBPsK[c];
  
 -          e->scalingFunction[BLACK] = &ScaleKPsK[BLACK];
 +        else if (is_KQKRPs(pos, c))
 +            e->scalingFunction[c] = &ScaleKQKRPs[c];
        }
 -      else if (pos.count<PAWN>(WHITE) == 1 && pos.count<PAWN>(BLACK) == 1)
 +
 +      if (npm_w + npm_b == VALUE_ZERO && pos.pieces(PAWN)) // Only pawns on the board
        {
 -          // This is a special case because we set scaling functions
 -          // for both colors instead of only one.
 -          e->scalingFunction[WHITE] = &ScaleKPKP[WHITE];
 -          e->scalingFunction[BLACK] = &ScaleKPKP[BLACK];
 +          if (!pos.count<PAWN>(BLACK))
 +          {
 +              assert(pos.count<PAWN>(WHITE) >= 2);
 +
 +              e->scalingFunction[WHITE] = &ScaleKPsK[WHITE];
 +          }
 +          else if (!pos.count<PAWN>(WHITE))
 +          {
 +              assert(pos.count<PAWN>(BLACK) >= 2);
 +
 +              e->scalingFunction[BLACK] = &ScaleKPsK[BLACK];
 +          }
 +          else if (pos.count<PAWN>(WHITE) == 1 && pos.count<PAWN>(BLACK) == 1)
 +          {
 +              // This is a special case because we set scaling functions
 +              // for both colors instead of only one.
 +              e->scalingFunction[WHITE] = &ScaleKPKP[WHITE];
 +              e->scalingFunction[BLACK] = &ScaleKPKP[BLACK];
 +          }
        }
 -  }
  
 -  // Zero or just one pawn makes it difficult to win, even with a small material
 -  // advantage. This catches some trivial draws like KK, KBK and KNK and gives a
 -  // drawish scale factor for cases such as KRKBP and KmmKm (except for KBBKN).
 -  if (!pos.count<PAWN>(WHITE) && npm_w - npm_b <= BishopValueMg)
 -      e->factor[WHITE] = uint8_t(npm_w <  RookValueMg   ? SCALE_FACTOR_DRAW :
 -                                 npm_b <= BishopValueMg ? 4 : 14);
 +      // Zero or just one pawn makes it difficult to win, even with a small material
 +      // advantage. This catches some trivial draws like KK, KBK and KNK and gives a
 +      // drawish scale factor for cases such as KRKBP and KmmKm (except for KBBKN).
 +      if (!pos.count<PAWN>(WHITE) && npm_w - npm_b <= BishopValueMg)
 +          e->factor[WHITE] = uint8_t(npm_w <  RookValueMg   ? SCALE_FACTOR_DRAW :
 +                                    npm_b <= BishopValueMg ? 4 : 14);
  
 -  if (!pos.count<PAWN>(BLACK) && npm_b - npm_w <= BishopValueMg)
 -      e->factor[BLACK] = uint8_t(npm_b <  RookValueMg   ? SCALE_FACTOR_DRAW :
 -                                 npm_w <= BishopValueMg ? 4 : 14);
 +      if (!pos.count<PAWN>(BLACK) && npm_b - npm_w <= BishopValueMg)
 +          e->factor[BLACK] = uint8_t(npm_b <  RookValueMg   ? SCALE_FACTOR_DRAW :
 +                                    npm_w <= BishopValueMg ? 4 : 14);
 +  }
  
    // Evaluate the material imbalance. We use PIECE_TYPE_NONE as a place holder
    // for the bishop pair "extended piece", which allows us to be more flexible
diff --cc src/pawns.cpp
@@@ -119,9 -117,8 +118,9 @@@ namespace 
              && popcount(phalanx) >= popcount(leverPush))
              e->passedPawns[Us] |= s;
  
 -        else if (   stoppers == square_bb(s + Up)
 -                 && relative_rank(Us, s) >= RANK_5)
 +        else if (   relative_rank(Them, s, pos.max_rank()) > RANK_1
-                  && stoppers == SquareBB[s + Up]
++                 && stoppers == square_bb(s + Up)
 +                 && relative_rank(Us, s, pos.max_rank()) >= RANK_5)
          {
              b = shift<Up>(support) & ~theirPawns;
              while (b)
@@@ -235,7 -207,7 +234,7 @@@ Value Entry::evaluate_shelter(const Pos
    Value safety = (shift<Down>(theirPawns) & (FileABB | FileHBB) & BlockRanks & ksq) ?
                   Value(374) : Value(5);
  
-   File center = std::max(FILE_B, std::min(File(pos.max_file() - 1), file_of(ksq)));
 -  File center = clamp(file_of(ksq), FILE_B, FILE_G);
++  File center = clamp(file_of(ksq), FILE_B, File(pos.max_file() - 1));
    for (File f = File(center - 1); f <= File(center + 1); ++f)
    {
        b = ourPawns & file_bb(f);
Simple merge
diff --cc src/position.h
Simple merge
diff --cc src/search.cpp
Simple merge
diff --cc src/thread.cpp
Simple merge
diff --cc src/timeman.cpp
Simple merge
Simple merge