Merge official-stockfish/master
authorFabian Fichter <ianfab@users.noreply.github.com>
Sat, 6 Apr 2019 13:05:36 +0000 (15:05 +0200)
committerFabian Fichter <ianfab@users.noreply.github.com>
Sat, 6 Apr 2019 13:05:36 +0000 (15:05 +0200)
bench: 3258421

1  2 
.travis.yml
src/bitboard.cpp
src/bitboard.h
src/endgame.cpp
src/evaluate.cpp
src/main.cpp
src/material.cpp
src/pawns.cpp
src/search.cpp
src/thread.cpp

diff --cc .travis.yml
Simple merge
  uint8_t PopCnt16[1 << 16];
  uint8_t SquareDistance[SQUARE_NB][SQUARE_NB];
  
- Bitboard BoardSizeBB[FILE_NB][RANK_NB];
- Bitboard SquareBB[SQUARE_NB];
- Bitboard ForwardRanksBB[COLOR_NB][RANK_NB];
  Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
  Bitboard LineBB[SQUARE_NB][SQUARE_NB];
 -Bitboard DistanceRingBB[SQUARE_NB][8];
 -Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
 -Bitboard PawnAttacks[COLOR_NB][SQUARE_NB];
 +Bitboard DistanceRingBB[SQUARE_NB][FILE_NB];
 +Bitboard PseudoAttacks[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
 +Bitboard PseudoMoves[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
 +Bitboard LeaperAttacks[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
 +Bitboard LeaperMoves[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
+ Bitboard SquareBB[SQUARE_NB];
++Bitboard BoardSizeBB[FILE_NB][RANK_NB];
  
  Bitboard KingFlank[FILE_NB] = {
    QueenSide ^ FileDBB, QueenSide, QueenSide,
diff --cc src/bitboard.h
@@@ -95,20 -68,14 +95,20 @@@ constexpr Bitboard Center      = (FileD
  extern uint8_t PopCnt16[1 << 16];
  extern uint8_t SquareDistance[SQUARE_NB][SQUARE_NB];
  
- extern Bitboard BoardSizeBB[FILE_NB][RANK_NB];
- extern Bitboard SquareBB[SQUARE_NB];
  extern Bitboard BetweenBB[SQUARE_NB][SQUARE_NB];
  extern Bitboard LineBB[SQUARE_NB][SQUARE_NB];
 -extern Bitboard DistanceRingBB[SQUARE_NB][8];
 -extern Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB];
 -extern Bitboard PawnAttacks[COLOR_NB][SQUARE_NB];
 +extern Bitboard DistanceRingBB[SQUARE_NB][FILE_NB];
 +extern Bitboard PseudoAttacks[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
 +extern Bitboard PseudoMoves[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
 +extern Bitboard LeaperAttacks[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
 +extern Bitboard LeaperMoves[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
  extern Bitboard KingFlank[FILE_NB];
+ extern Bitboard SquareBB[SQUARE_NB];
++extern Bitboard BoardSizeBB[FILE_NB][RANK_NB];
  
 +#ifdef LARGEBOARDS
 +int popcount(Bitboard b); // required for 128 bit pext
 +#endif
  
  /// Magic holds all magic bitboards relevant data for a single square
  struct Magic {
  extern Magic RookMagics[SQUARE_NB];
  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 square_bb(Square s) {
 -  assert(s >= SQ_A1 && s <= SQ_H8);
 +  assert(s >= SQ_A1 && s <= SQ_MAX);
    return SquareBB[s];
  }
-   
+ /// 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) { 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); }
diff --cc src/endgame.cpp
Simple merge
@@@ -235,28 -224,25 +235,31 @@@ namespace 
      constexpr Color     Them = (Us == WHITE ? BLACK : WHITE);
      constexpr Direction Up   = (Us == WHITE ? NORTH : SOUTH);
      constexpr Direction Down = (Us == WHITE ? SOUTH : NORTH);
 -    constexpr Bitboard LowRanks = (Us == WHITE ? Rank2BB | Rank3BB: Rank7BB | Rank6BB);
 +    Bitboard LowRanks = rank_bb(relative_rank(Us, RANK_2, pos.max_rank())) | rank_bb(relative_rank(Us, RANK_3, pos.max_rank()));
  
 -    const Square ksq = pos.square<KING>(Us);
 +    const Square ksq = pos.count<KING>(Us) ? pos.square<KING>(Us) : SQ_NONE;
  
+     Bitboard dblAttackByPawn = pawn_double_attacks_bb<Us>(pos.pieces(Us, PAWN));
      // Find our pawns that are blocked or on the first two ranks
      Bitboard b = pos.pieces(Us, PAWN) & (shift<Down>(pos.pieces()) | LowRanks);
  
      // Squares occupied by those pawns, by our king or queen or controlled by
      // enemy pawns are excluded from the mobility area.
 -    mobilityArea[Us] = ~(b | pos.pieces(Us, KING, QUEEN) | pe->pawn_attacks(Them));
 +    if (pos.must_capture())
 +        mobilityArea[Us] = AllSquares;
 +    else
 +        mobilityArea[Us] = ~(b | pos.pieces(Us, KING, QUEEN) | pe->pawn_attacks(Them) | shift<Down>(pos.pieces(Them, SHOGI_PAWN)));
  
      // Initialize attackedBy[] for king and pawns
 -    attackedBy[Us][KING] = pos.attacks_from<KING>(ksq);
 +    attackedBy[Us][KING] = pos.count<KING>(Us) ? pos.attacks_from<KING>(Us, ksq) : 0;
      attackedBy[Us][PAWN] = pe->pawn_attacks(Us);
 -    attackedBy[Us][ALL_PIECES] = attackedBy[Us][KING] | attackedBy[Us][PAWN];
 -    attackedBy2[Us]            = (attackedBy[Us][KING] & attackedBy[Us][PAWN])
 -                                 | dblAttackByPawn;
 +    attackedBy[Us][SHOGI_PAWN] = shift<Up>(pos.pieces(Us, SHOGI_PAWN));
 +    attackedBy[Us][ALL_PIECES] = attackedBy[Us][KING] | attackedBy[Us][PAWN] | attackedBy[Us][SHOGI_PAWN];
 +    attackedBy2[Us]            =  (attackedBy[Us][KING] & attackedBy[Us][PAWN])
 +                                | (attackedBy[Us][KING] & attackedBy[Us][SHOGI_PAWN])
-                                 | (attackedBy[Us][PAWN] & attackedBy[Us][SHOGI_PAWN]);
++                                | (attackedBy[Us][PAWN] & attackedBy[Us][SHOGI_PAWN])
++                                | dblAttackByPawn;
  
      // Init our king safety tables
      kingRing[Us] = attackedBy[Us][KING];
      kingAttacksCount[Them] = kingAttackersWeight[Them] = 0;
  
      // Remove from kingRing[] the squares defended by two pawns
-     kingRing[Us] &= ~pawn_double_attacks_bb<Us>(pos.pieces(Us, PAWN));
+     kingRing[Us] &= ~dblAttackByPawn;
 +
 +    kingRing[Us] &= pos.board_bb();
    }
  
  
diff --cc src/main.cpp
Simple merge
@@@ -141,99 -132,76 +141,99 @@@ Entry* probe(const Position& pos) 
    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));
 -
 +  if (pos.captures_to_hand())
 +  {
 +      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);
 +  }
 +  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
 +  {
-       // 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)
+   // 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_KFsPsK(pos, c))
++      {
++          e->evaluationFunction = &EvaluateKFsPsK[c];
 +          return e;
++      }
 +
-       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)
++  for (Color c = WHITE; c <= BLACK; ++c)
+       if (is_KXK(pos, c))
        {
-           e->scalingFunction[sf->strongSide] = sf; // Only strong color assigned
+           e->evaluationFunction = &EvaluateKXK[c];
            return e;
        }
  
-       // 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)
+   // OK, we didn't find any special evaluation function for the current material
+   // configuration. Is there a suitable specialized scaling function?
+   const auto* sf = pos.this_thread()->endgames.probe<ScaleFactor>(key);
+   if (sf)
+   {
+       e->scalingFunction[sf->strongSide] = sf; // Only strong color assigned
+       return e;
+   }
+   // 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)
+   {
+     if (is_KBPsK(pos, c))
+         e->scalingFunction[c] = &ScaleKBPsK[c];
+     else if (is_KQKRPs(pos, c))
+         e->scalingFunction[c] = &ScaleKQKRPs[c];
+   }
+   if (npm_w + npm_b == VALUE_ZERO && pos.pieces(PAWN)) // Only pawns on the board
+   {
+       if (!pos.count<PAWN>(BLACK))
        {
-         if (is_KBPsK(pos, c))
-             e->scalingFunction[c] = &ScaleKBPsK[c];
+           assert(pos.count<PAWN>(WHITE) >= 2);
  
-         else if (is_KQKRPs(pos, c))
-             e->scalingFunction[c] = &ScaleKQKRPs[c];
+           e->scalingFunction[WHITE] = &ScaleKPsK[WHITE];
        }
+       else if (!pos.count<PAWN>(WHITE))
+       {
+           assert(pos.count<PAWN>(BLACK) >= 2);
  
-       if (npm_w + npm_b == VALUE_ZERO && pos.pieces(PAWN)) // Only pawns on the board
+           e->scalingFunction[BLACK] = &ScaleKPsK[BLACK];
+       }
+       else if (pos.count<PAWN>(WHITE) == 1 && pos.count<PAWN>(BLACK) == 1)
        {
-           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];
-           }
+           // 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
@@@ -130,10 -128,14 +130,14 @@@ namespace 
  
          // Score this pawn
          if (support | phalanx)
-             score += Connected[opposed][bool(phalanx)][popcount(support)][relative_rank(Us, s, pos.max_rank())];
+         {
 -            int r = relative_rank(Us, s);
++            int r = relative_rank(Us, s, pos.max_rank());
+             int v = phalanx ? Connected[r] + Connected[r + 1] : 2 * Connected[r];
+             v = 17 * popcount(support) + (v >> (opposed + 1));
+             score += make_score(v, v * (r - 2) / 4);
+         }
          else if (!neighbours)
 -            score -= Isolated, e->weakUnopposed[Us] += !opposed;
 +            score -= Isolated * (1 + 2 * pos.must_capture()), e->weakUnopposed[Us] += !opposed;
  
          else if (backward)
              score -= Backward, e->weakUnopposed[Us] += !opposed;
              score -= Doubled;
      }
  
 +    const Square* pl_shogi = pos.squares<SHOGI_PAWN>(Us);
 +
 +    ourPawns   = pos.pieces(Us,   SHOGI_PAWN);
 +    theirPawns = pos.pieces(Them, SHOGI_PAWN);
 +
 +    // Loop through all shogi pawns of the current color and score each one
 +    while ((s = *pl_shogi++) != SQ_NONE)
 +    {
 +        assert(pos.piece_on(s) == make_piece(Us, SHOGI_PAWN));
 +
 +        File f = file_of(s);
 +
 +        e->semiopenFiles[Us] &= ~(1 << f);
 +
-         opposed    = theirPawns & forward_file_bb(Us, s);
 +        neighbours = ourPawns   & adjacent_files_bb(f);
-         phalanx    = neighbours & rank_bb(s);
-         if (phalanx)
-             score += Connected[opposed][bool(phalanx)][0][relative_rank(Us, s, pos.max_rank())] / 2;
 +
-         else if (!neighbours)
++        if (!neighbours)
 +            score -= Isolated / 2;
 +    }
 +
      return score;
    }
  
diff --cc src/search.cpp
@@@ -724,13 -724,12 +729,12 @@@ namespace 
          {
              int bonus = -(ss-1)->statScore / 512;
  
-             pureStaticEval = evaluate(pos);
-             ss->staticEval = eval = pureStaticEval + bonus;
+             ss->staticEval = eval = evaluate(pos) + bonus;
          }
          else
-             ss->staticEval = eval = pureStaticEval = -(ss-1)->staticEval + 2 * Eval::tempo_value(pos);
 -            ss->staticEval = eval = -(ss-1)->staticEval + 2 * Eval::Tempo;
++            ss->staticEval = eval = -(ss-1)->staticEval + 2 * Eval::tempo_value(pos);
  
-         tte->save(posKey, VALUE_NONE, ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, pureStaticEval);
+         tte->save(posKey, VALUE_NONE, ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, eval);
      }
  
      // Step 7. Razoring (~2 Elo)
          && (ss-1)->currentMove != MOVE_NULL
          && (ss-1)->statScore < 23200
          &&  eval >= beta
-         &&  pureStaticEval >= beta - 36 * depth / ONE_PLY + 225
+         &&  ss->staticEval >= 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);
      }
  
      // Step 11. Internal iterative deepening (~2 Elo)
-     if (    depth >= (8 - 2 * pos.captures_to_hand()) * ONE_PLY
-         && !ttMove)
 -    if (depth >= 8 * ONE_PLY && !ttMove)
++    if (depth >= (8 - 2 * pos.captures_to_hand()) * ONE_PLY && !ttMove)
      {
 -        search<NT>(pos, ss, alpha, beta, depth - 7 * ONE_PLY, cutNode);
 +        search<NT>(pos, ss, alpha, beta, depth - (7 - 2 * pos.captures_to_hand()) * ONE_PLY, cutNode);
  
          tte = TT.probe(posKey, ttHit);
          ttValue = ttHit ? value_from_tt(tte->value(), ss->ply) : VALUE_NONE;
diff --cc src/thread.cpp
Simple merge