Merge official-stockfish/master
authorFabian Fichter <ianfab@users.noreply.github.com>
Sat, 23 Feb 2019 13:50:16 +0000 (14:50 +0100)
committerFabian Fichter <ianfab@users.noreply.github.com>
Sat, 23 Feb 2019 13:50:16 +0000 (14:50 +0100)
bench: 4439882

14 files changed:
1  2 
Readme.md
src/bitboard.cpp
src/endgame.cpp
src/evaluate.cpp
src/material.cpp
src/movepick.h
src/pawns.cpp
src/psqt.cpp
src/search.cpp
src/syzygy/tbprobe.cpp
src/thread.cpp
src/tt.cpp
src/types.h
src/ucioption.cpp

diff --cc Readme.md
Simple merge
@@@ -401,252 -116,46 +401,252 @@@ void Bitboards::init() 
            if (s1 != s2)
            {
                SquareDistance[s1][s2] = std::max(distance<File>(s1, s2), distance<Rank>(s1, s2));
-               DistanceRingBB[s1][SquareDistance[s1][s2] - 1] |= s2;
+               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)
 +          for (Square s2 = SQ_A1; s2 <= SQ_MAX; ++s2)
            {
 -              if (!(PseudoAttacks[pt][s1] & s2))
 +              if (!(PseudoAttacks[WHITE][pt][s1] & s2))
                    continue;
  
 -              LineBB[s1][s2] = (attacks_bb(pt, s1, 0) & attacks_bb(pt, s2, 0)) | s1 | s2;
 -              BetweenBB[s1][s2] = attacks_bb(pt, s1, SquareBB[s2]) & attacks_bb(pt, s2, SquareBB[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]);
            }
    }
  }
diff --cc src/endgame.cpp
Simple merge
@@@ -474,20 -408,25 +473,29 @@@ namespace 
    Score Evaluation<T>::king() const {
  
      constexpr Color    Them = (Us == WHITE ? BLACK : WHITE);
 -    constexpr Bitboard Camp = (Us == WHITE ? AllSquares ^ Rank6BB ^ Rank7BB ^ Rank8BB
 -                                           : AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB);
 +    Rank r = relative_rank(Us, std::min(Rank((pos.max_rank() - 1) / 2 + 1), pos.max_rank()), pos.max_rank());
 +    Bitboard Camp = AllSquares ^ forward_ranks_bb(Us, r);
 +
 +    if (!pos.count<KING>(Us) || !pos.checking_permitted())
 +        return SCORE_ZERO;
  
      const Square ksq = pos.square<KING>(Us);
-     Bitboard weak, b, b1, b2, safe, unsafeChecks;
+     Bitboard kingFlank, weak, b, b1, b2, safe, unsafeChecks;
  
      // King shelter and enemy pawns storm
      Score score = pe->king_safety<Us>(pos, ksq);
  
+     // Find the squares that opponent attacks in our king flank, and the squares
+     // which are attacked twice in that flank but not defended by our pawns.
 -    kingFlank = KingFlank[file_of(ksq)];
++    File f = std::max(std::min(file_of(ksq), File(pos.max_file() - 1)), FILE_B);
++    kingFlank = pos.max_file() == FILE_H ? KingFlank[file_of(ksq)] : file_bb(f) | adjacent_files_bb(f);
+     b1 = attackedBy[Them][ALL_PIECES] & kingFlank & Camp;
 -    b2 = b1 & attackedBy2[Them] & ~attackedBy[Us][PAWN];
++    b2 = b1 & attackedBy2[Them] & ~attackedBy[Us][PAWN] & ~attackedBy[Us][SHOGI_PAWN];
+     int tropism = popcount(b1) + popcount(b2);
      // Main king safety evaluation
 -    if (kingAttackersCount[Them] > 1 - pos.count<QUEEN>(Them))
 +    if ((kingAttackersCount[Them] > 1 - pos.count<QUEEN>(Them)) || pos.captures_to_hand())
      {
          int kingDanger = 0;
          unsafeChecks = 0;
          unsafeChecks &= mobilityArea[Them];
  
          kingDanger +=        kingAttackersCount[Them] * kingAttackersWeight[Them]
 -                     +  69 * kingAttacksCount[Them]
 -                     + 185 * popcount(kingRing[Us] & weak)
 +                     + 69  * kingAttacksCount[Them] * (1 + 2 * !!pos.max_check_count())
 +                     + 185 * popcount(kingRing[Us] & weak) * (1 + pos.captures_to_hand() + !!pos.max_check_count())
-                      + 129 * popcount(pos.blockers_for_king(Us) | unsafeChecks)
+                      + 150 * popcount(pos.blockers_for_king(Us) | unsafeChecks)
+                      +   4 * tropism
 -                     - 873 * !pos.count<QUEEN>(Them)
 +                     - 873 * !(pos.count<QUEEN>(Them) || pos.captures_to_hand()) / (1 + !!pos.max_check_count())
                       -   6 * mg_value(score) / 8
-                      -   2;
+                      -   30;
  
          // Transform the kingDanger units into a Score, and subtract it from the evaluation
          if (kingDanger > 0)
          }
      }
  
-     File f = std::max(std::min(file_of(ksq), File(pos.max_file() - 1)), FILE_B);
-     Bitboard kf = pos.max_file() == FILE_H ? KingFlank[f] : file_bb(f) | adjacent_files_bb(f);
      // Penalty when our king is on a pawnless flank
-     if (!(pos.pieces(PAWN) & kf))
+     if (!(pos.pieces(PAWN) & kingFlank))
          score -= PawnlessFlank;
  
-     // Find the squares that opponent attacks in our king flank, and the squares
-     // which are attacked twice in that flank but not defended by our pawns.
-     b1 = attackedBy[Them][ALL_PIECES] & kf & Camp;
-     b2 = b1 & attackedBy2[Them] & ~(attackedBy[Us][PAWN] | attackedBy[Us][SHOGI_PAWN]);
-     // King tropism, to anticipate slow motion attacks on our king
-     score -= CloseEnemies * (popcount(b1) + popcount(b2)) * (1 + pos.captures_to_hand() + !!pos.max_check_count());
+     // King tropism bonus, to anticipate slow motion attacks on our king
 -    score -= CloseEnemies * tropism;
++    score -= CloseEnemies * tropism * (1 + pos.captures_to_hand() + !!pos.max_check_count());
 +
 +    // For drop games, king danger is independent of game phase
 +    if (pos.captures_to_hand())
 +        score = make_score(mg_value(score), mg_value(score)) / (1 + !pos.shogi_doubled_pawn());
  
      if (T)
          Trace::add(KING, Us, score);
          {
              Square s = pop_lsb(&b);
              score += ThreatByMinor[type_of(pos.piece_on(s))];
 -            if (type_of(pos.piece_on(s)) != PAWN)
 -                score += ThreatByRank * (int)relative_rank(Them, s);
 +            if (type_of(pos.piece_on(s)) != PAWN && type_of(pos.piece_on(s)) != SHOGI_PAWN)
 +                score += ThreatByRank * (int)relative_rank(Them, s, pos.max_rank());
-             else if (pos.blockers_for_king(Them) & s)
-                 score += ThreatByRank * (int)relative_rank(Them, s, pos.max_rank()) / 2;
          }
  
          b = weak & attackedBy[Us][ROOK];
          {
              Square s = pop_lsb(&b);
              score += ThreatByRook[type_of(pos.piece_on(s))];
 -            if (type_of(pos.piece_on(s)) != PAWN)
 -                score += ThreatByRank * (int)relative_rank(Them, s);
 +            if (type_of(pos.piece_on(s)) != PAWN && type_of(pos.piece_on(s)) != SHOGI_PAWN)
 +                score += ThreatByRank * (int)relative_rank(Them, s, pos.max_rank());
-             else if (pos.blockers_for_king(Them) & s)
-                 score += ThreatByRank * (int)relative_rank(Them, s, pos.max_rank()) / 2;
          }
  
          if (weak & attackedBy[Us][KING])
  
          assert(!(pos.pieces(Them, PAWN) & forward_file_bb(Us, s + Up)));
  
-         if (forward_file_bb(Us, s) & pos.pieces(Them))
-             score -= HinderPassedPawn;
 -        int r = relative_rank(Us, s);
 +        int r = relative_rank(Us, s, pos.max_rank());
          int w = PassedDanger[r];
  
          Score bonus = PassedRank[r];
    template<Tracing T> template<Color Us>
    Score Evaluation<T>::space() const {
  
-     constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
-     constexpr Bitboard SpaceMask =
-       Us == WHITE ? CenterFiles & (Rank2BB | Rank3BB | Rank4BB)
-                   : CenterFiles & (Rank7BB | Rank6BB | Rank5BB);
 -    if (pos.non_pawn_material() < SpaceThreshold)
 +    bool pawnsOnly = !(pos.pieces(Us) ^ pos.pieces(Us, PAWN));
 +
 +    if (pos.non_pawn_material() < SpaceThreshold && !pos.captures_to_hand() && !pawnsOnly)
          return SCORE_ZERO;
  
+     constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
+     constexpr Bitboard SpaceMask =
+       Us == WHITE ? CenterFiles & (Rank2BB | Rank3BB | Rank4BB)
+                   : CenterFiles & (Rank7BB | Rank6BB | Rank5BB);
      // Find the available squares for our pieces inside the area defined by SpaceMask
      Bitboard safe =   SpaceMask
 -                   & ~pos.pieces(Us, PAWN)
 -                   & ~attackedBy[Them][PAWN];
 +                   & ~pos.pieces(Us, PAWN, SHOGI_PAWN)
 +                   & ~attackedBy[Them][PAWN]
 +                   & ~attackedBy[Them][SHOGI_PAWN];
 +
 +    if (pawnsOnly)
 +        safe = pos.pieces(Us, PAWN) & ~attackedBy[Them][ALL_PIECES];
  
      // Find all squares which are at most three squares behind some friendly pawn
 -    Bitboard behind = pos.pieces(Us, PAWN);
 -    behind |= (Us == WHITE ? behind >>  8 : behind <<  8);
 -    behind |= (Us == WHITE ? behind >> 16 : behind << 16);
 +    Bitboard behind = pos.pieces(Us, PAWN, SHOGI_PAWN);
 +    behind |= (Us == WHITE ? behind >> NORTH : behind << NORTH);
 +    behind |= (Us == WHITE ? behind >> (2 * NORTH) : behind << (2 * NORTH));
 +
  
      int bonus = popcount(safe) + popcount(behind & safe);
      int weight = pos.count<ALL_PIECES>(Us) - 2 * pe->open_files();
Simple merge
diff --cc src/movepick.h
Simple merge
diff --cc src/pawns.cpp
@@@ -239,12 -211,10 +238,10 @@@ Value Entry::evaluate_shelter(const Pos
    Bitboard ourPawns = b & pos.pieces(Us);
    Bitboard theirPawns = b & pos.pieces(Them);
  
-   Value safety = (ourPawns & file_bb(ksq)) ? Value(5) : Value(-5);
-   if (shift<Down>(theirPawns) & (FileABB | FileHBB) & BlockRanks & ksq)
-       safety += Value(374);
+   Value safety = (shift<Down>(theirPawns) & (FileABB | FileHBB) & BlockRanks & ksq) ?
+                  Value(374) : Value(5);
  
 -  File center = std::max(FILE_B, std::min(FILE_G, file_of(ksq)));
 +  File center = std::max(FILE_B, std::min(File(pos.max_file() - 1), file_of(ksq)));
    for (File f = File(center - 1); f <= File(center + 1); ++f)
    {
        b = ourPawns & file_bb(f);
diff --cc src/psqt.cpp
@@@ -44,16 -35,16 +44,16 @@@ namespace PSQT 
  // type on a given square a (middlegame, endgame) score pair is assigned. Table
  // is defined for files A..D and white side: it is symmetric for black side and
  // second half of the files.
 -constexpr Score Bonus[][RANK_NB][int(FILE_NB) / 2] = {
 +constexpr Score Bonus[PIECE_TYPE_NB][RANK_NB][int(FILE_NB) / 2] = {
    { },
    { // Pawn
-    { S(  0, 0), S(  0, 0), S(  0, 0), S( 0, 0) },
-    { S(-11, 7), S(  6,-4), S(  7, 8), S( 3,-2) },
-    { S(-18,-4), S( -2,-5), S( 19, 5), S(24, 4) },
-    { S(-17, 3), S( -9, 3), S( 20,-8), S(35,-3) },
-    { S( -6, 8), S(  5, 9), S(  3, 7), S(21,-6) },
-    { S( -6, 8), S( -8,-5), S( -6, 2), S(-2, 4) },
-    { S( -4, 3), S( 20,-9), S( -8, 1), S(-4,18) }
+    { S(  0, 0), S(  0,  0), S(  0, 0), S( 0, 0) },
+    { S(-11,-3), S(  7, -1), S(  7, 7), S(17, 2) },
+    { S(-16,-2), S( -3,  2), S( 23, 6), S(23,-1) },
+    { S(-14, 7), S( -7, -4), S( 20,-8), S(24, 2) },
+    { S( -5,13), S( -2, 10), S( -1,-1), S(12,-8) },
+    { S(-11,16), S(-12,  6), S( -2, 1), S( 4,16) },
+    { S( -2, 1), S( 20,-12), S(-10, 6), S(-2,25) }
    },
    { // Knight
     { S(-161,-105), S(-96,-82), S(-80,-46), S(-73,-14) },
     { S(-2,-40), S( 6,-16), S( 8,-10), S(10,  3) },
     { S(-2,-55), S( 7,-30), S( 7,-21), S( 6, -6) },
     { S(-1,-74), S(-4,-55), S(-1,-43), S( 0,-30) }
 -  },
 -  { // King
 +  }
 +};
 +
 +constexpr Score KingBonus[RANK_NB][int(FILE_NB) / 2] = {
-    { S(267,  0), S(320, 48), S(270, 75), S(195, 84) },
-    { S(264, 43), S(304, 92), S(238,143), S(180,132) },
-    { S(200, 83), S(245,138), S(176,167), S(110,165) },
-    { S(177,106), S(185,169), S(148,169), S(110,179) },
-    { S(149,108), S(177,163), S(115,200), S( 66,203) },
-    { S(118, 95), S(159,155), S( 84,176), S( 41,174) },
-    { S( 87, 50), S(128, 99), S( 63,122), S( 20,139) },
-    { S( 63,  9), S( 88, 55), S( 47, 80), S(  0, 90) }
+    { S(272,  0), S(325, 41), S(273, 80), S(190, 93) },
+    { S(277, 57), S(305, 98), S(241,138), S(183,131) },
+    { S(198, 86), S(253,138), S(168,165), S(120,173) },
+    { S(169,103), S(191,152), S(136,168), S(108,169) },
+    { S(145, 98), S(176,166), S(112,197), S(69, 194) },
+    { S(122, 87), S(159,164), S(85, 174), S(36, 189) },
+    { S(87,  40), S(120, 99), S(64, 128), S(25, 141) },
+    { S(64,   5), S(87,  60), S(49,  75), S(0,   75) }
 -  }
  };
  
  #undef S
diff --cc src/search.cpp
@@@ -567,14 -587,12 +589,15 @@@ namespace 
  
      if (!rootNode)
      {
 +        Value variantResult;
 +        if (pos.is_game_end(variantResult, ss->ply))
 +            return variantResult;
 +
          // Step 2. Check for aborted search and immediate draw
          if (   Threads.stop.load(std::memory_order_relaxed)
 -            || pos.is_draw(ss->ply)
              || ss->ply >= MAX_PLY)
-             return (ss->ply >= MAX_PLY && !inCheck) ? evaluate(pos) : VALUE_DRAW;
+             return (ss->ply >= MAX_PLY && !inCheck) ? evaluate(pos) 
+                                                     : value_draw(depth, pos.this_thread());
  
          // Step 3. Mate distance pruning. Even if we mate at the next move our score
          // would be at best mate_in(ss->ply+1), but if alpha is already bigger because
      }
      else
      {
-         ss->staticEval = eval =
-         (ss-1)->currentMove != MOVE_NULL ? evaluate(pos)
-                                          : -(ss-1)->staticEval + 2 * Eval::tempo_value(pos);
+         if ((ss-1)->currentMove != MOVE_NULL)
+         {
+             int p = (ss-1)->statScore;
+             int bonus = p > 0 ? (-p - 2500) / 512 :
+                         p < 0 ? (-p + 2500) / 512 : 0;
  
-         tte->save(posKey, VALUE_NONE, BOUND_NONE, DEPTH_NONE, MOVE_NONE,
-                   ss->staticEval);
+             pureStaticEval = evaluate(pos);
+             ss->staticEval = eval = pureStaticEval + bonus;
+         }
+         else
 -            ss->staticEval = eval = pureStaticEval = -(ss-1)->staticEval + 2 * Eval::Tempo;
++            ss->staticEval = eval = pureStaticEval = -(ss-1)->staticEval + 2 * Eval::tempo_value(pos);
+         tte->save(posKey, VALUE_NONE, BOUND_NONE, DEPTH_NONE, MOVE_NONE, pureStaticEval);
      }
  
      // Step 7. Razoring (~2 Elo)
-     if (  !PvNode
-         && depth < 3 * ONE_PLY
+     if (   depth < 2 * ONE_PLY
 +        && !pos.must_capture()
 +        && !pos.capture_the_flag_piece()
 +        && !pos.max_check_count()
-         && eval <= alpha - RazorMargin[depth / ONE_PLY])
-     {
-         Value ralpha = alpha - (depth >= 2 * ONE_PLY) * RazorMargin[depth / ONE_PLY];
-         Value v = qsearch<NonPV>(pos, ss, ralpha, ralpha+1);
-         if (depth < 2 * ONE_PLY || v <= ralpha)
-             return v;
-     }
+         && eval <= alpha - RazorMargin)
+         return qsearch<NT>(pos, ss, alpha, beta);
  
      improving =   ss->staticEval >= (ss-2)->staticEval
                 || (ss-2)->staticEval == VALUE_NONE;
      // Step 9. Null move search with verification search (~40 Elo)
      if (   !PvNode
          && (ss-1)->currentMove != MOVE_NULL
-         && (ss-1)->statScore < 22500
+         && (ss-1)->statScore < 23200
          &&  eval >= beta
-         &&  ss->staticEval >= beta - 36 * depth / ONE_PLY + 225
+         &&  pureStaticEval >= beta - 36 * depth / ONE_PLY + 225
          && !excludedMove
          &&  pos.non_pawn_material(us)
 +        && (pos.pieces(~us) ^ pos.pieces(~us, PAWN))
 +        && (pos.pieces() ^ pos.pieces(BREAKTHROUGH_PIECE) ^ pos.pieces(CLOBBER_PIECE))
          && (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor))
      {
          assert(eval - beta >= 0);
  
          // Null move dynamic reduction based on depth and value
-         Depth R = ((823 - 150 * !pos.checking_permitted() + 67 * depth / ONE_PLY) / 256 + std::min((eval - beta) / PawnValueMg, 3)) * ONE_PLY;
 -        Depth R = ((823 + 67 * depth / ONE_PLY) / 256 + std::min(int(eval - beta) / 200, 3)) * ONE_PLY;
++        Depth R = ((823 - 150 * !pos.checking_permitted() + 67 * depth / ONE_PLY) / 256 + std::min(int(eval - beta) / 200, 3)) * ONE_PLY;
  
          ss->currentMove = MOVE_NULL;
-         ss->continuationHistory = thisThread->continuationHistory[NO_PIECE][0].get();
+         ss->continuationHistory = &thisThread->continuationHistory[NO_PIECE][0];
  
          pos.do_null_move(st);
  
@@@ -926,13 -933,8 +951,12 @@@ moves_loop: // When in check, search st
                extension = ONE_PLY;
        }
        else if (    givesCheck // Check extension (~2 Elo)
-                && !moveCountPruning
                 &&  pos.see_ge(move))
            extension = ONE_PLY;
 +      else if (    pos.must_capture() // Capture extension (all moves are captures)
 +               &&  pos.capture(move)
 +               &&  MoveList<CAPTURES>(pos).size() == 1)
 +          extension = ONE_PLY;
  
        // Calculate new depth for this move
        newDepth = depth - ONE_PLY + extension;
        {
            Depth r = reduction<PvNode>(improving, depth, moveCount);
  
-           if (captureOrPromotion || (pos.must_capture() && MoveList<CAPTURES>(pos).size())) // (~5 Elo)
-           {
-               // Decrease reduction by comparing opponent's stat score
-               if ((ss-1)->statScore < 0)
-                   r -= ONE_PLY;
-           }
-           else
-           {
-               // Decrease reduction if opponent's move count is high (~5 Elo)
-               if ((ss-1)->moveCount > 15)
-                   r -= ONE_PLY;
+           // Decrease reduction if opponent's move count is high (~10 Elo)
+           if ((ss-1)->moveCount > 15)
+               r -= ONE_PLY;
  
 -          if (!captureOrPromotion)
++          if (!captureOrPromotion && !(pos.must_capture() && MoveList<CAPTURES>(pos).size()))
+           {
                // Decrease reduction for exact PV nodes (~0 Elo)
                if (pvExact)
                    r -= ONE_PLY;
Simple merge
diff --cc src/thread.cpp
Simple merge
diff --cc src/tt.cpp
Simple merge
diff --cc src/types.h
@@@ -205,32 -182,11 +205,32 @@@ enum Value : int 
    VALUE_MATE_IN_MAX_PLY  =  VALUE_MATE - 2 * MAX_PLY,
    VALUE_MATED_IN_MAX_PLY = -VALUE_MATE + 2 * MAX_PLY,
  
-   PawnValueMg              = 171,   PawnValueEg              = 240,
-   KnightValueMg            = 764,   KnightValueEg            = 848,
-   BishopValueMg            = 826,   BishopValueEg            = 891,
-   RookValueMg              = 1282,  RookValueEg              = 1373,
-   QueenValueMg             = 2500,  QueenValueEg             = 2670,
 -  PawnValueMg   = 142,   PawnValueEg   = 207,
 -  KnightValueMg = 784,   KnightValueEg = 868,
 -  BishopValueMg = 828,   BishopValueEg = 916,
 -  RookValueMg   = 1286,  RookValueEg   = 1378,
 -  QueenValueMg  = 2528,  QueenValueEg  = 2698,
++  PawnValueMg              = 142,   PawnValueEg              = 207,
++  KnightValueMg            = 784,   KnightValueEg            = 868,
++  BishopValueMg            = 828,   BishopValueEg            = 916,
++  RookValueMg              = 1286,  RookValueEg              = 1378,
++  QueenValueMg             = 2528,  QueenValueEg             = 2698,
 +  FersValueMg              = 400,   FersValueEg              = 400,
 +  AlfilValueMg             = 300,   AlfilValueEg             = 300,
 +  SilverValueMg            = 600,   SilverValueEg            = 600,
 +  AiwokValueMg             = 2500,  AiwokValueEg             = 2500,
 +  BersValueMg              = 2000,  BersValueEg              = 2000,
 +  ArchbishopValueMg        = 2000,  ArchbishopValueEg        = 2000,
 +  ChancellorValueMg        = 2300,  ChancellorValueEg        = 2300,
 +  AmazonValueMg            = 3000,  AmazonValueEg            = 3000,
 +  KnibisValueMg            = 800,   KnibisValueEg            = 800,
 +  BiskniValueMg            = 800,   BiskniValueEg            = 800,
 +  ShogiPawnValueMg         = 100,   ShogiPawnValueEg         = 100,
 +  LanceValueMg             = 300,   LanceValueEg             = 300,
 +  ShogiKnightValueMg       = 300,   ShogiKnightValueEg       = 300,
 +  EuroShogiKnightValueMg   = 400,   EuroShogiKnightValueEg   = 400,
 +  GoldValueMg              = 600,   GoldValueEg              = 600,
 +  HorseValueMg             = 1500,  HorseValueEg             = 1500,
 +  ClobberPieceValueMg      = 300,   ClobberPieceValueEg      = 300,
 +  BreakthroughPieceValueMg = 300,   BreakthroughPieceValueEg = 300,
 +  ImmobilePieceValueMg     = 100,   ImmobilePieceValueEg     = 100,
 +  WazirValueMg             = 400,   WazirValueEg             = 400,
 +  CommonerValueMg          = 600,   CommonerValueEg          = 600,
  
    MidgameLimit  = 15258, EndgameLimit  = 3915
  };
Simple merge