Merge official-stockfish/master
authorFabian Fichter <ianfab@users.noreply.github.com>
Sun, 31 May 2020 21:51:58 +0000 (23:51 +0200)
committerFabian Fichter <ianfab@users.noreply.github.com>
Sun, 31 May 2020 21:51:58 +0000 (23:51 +0200)
No functional change.

1  2 
src/bitbase.cpp
src/bitboard.h
src/misc.cpp
src/position.cpp
src/position.h

diff --cc src/bitbase.cpp
@@@ -122,21 -113,21 +118,21 @@@ namespace 
      if (   distance(ksq[WHITE], ksq[BLACK]) <= 1
          || ksq[WHITE] == psq
          || ksq[BLACK] == psq
-         || (us == WHITE && (PseudoAttacks[WHITE][PAWN][psq] & ksq[BLACK])))
 -        || (stm == WHITE && (PawnAttacks[WHITE][psq] & ksq[BLACK])))
++        || (stm == WHITE && (PseudoAttacks[WHITE][PAWN][psq] & ksq[BLACK])))
          result = INVALID;
  
      // Immediate win if a pawn can be promoted without getting captured
-     else if (   us == WHITE
+     else if (   stm == WHITE
               && rank_of(psq) == RANK_7
-              && ksq[us] != psq + NORTH
-              && (    distance(ksq[~us], psq + NORTH) > 1
-                  || (PseudoAttacks[us][KING][ksq[us]] & (psq + NORTH))))
+              && ksq[stm] != psq + NORTH
+              && (    distance(ksq[~stm], psq + NORTH) > 1
 -                 || (PseudoAttacks[KING][ksq[stm]] & (psq + NORTH))))
++                 || (PseudoAttacks[stm][KING][ksq[stm]] & (psq + NORTH))))
          result = WIN;
  
      // Immediate draw if it is a stalemate or a king captures undefended pawn
-     else if (   us == BLACK
-              && (  !(PseudoAttacks[us][KING][ksq[us]] & ~(PseudoAttacks[us][KING][ksq[~us]] | PseudoAttacks[~us][PAWN][psq]))
-                  || (PseudoAttacks[us][KING][ksq[us]] & psq & ~PseudoAttacks[us][KING][ksq[~us]])))
+     else if (   stm == BLACK
 -             && (  !(PseudoAttacks[KING][ksq[stm]] & ~(PseudoAttacks[KING][ksq[~stm]] | PawnAttacks[~stm][psq]))
 -                 || (PseudoAttacks[KING][ksq[stm]] & psq & ~PseudoAttacks[KING][ksq[~stm]])))
++             && (  !(PseudoAttacks[stm][KING][ksq[stm]] & ~(PseudoAttacks[stm][KING][ksq[~stm]] | PseudoAttacks[~stm][PAWN][psq]))
++                 || (PseudoAttacks[stm][KING][ksq[stm]] & psq & ~PseudoAttacks[stm][KING][ksq[~stm]])))
          result = DRAW;
  
      // Position will be classified later
      // of the current position is DRAW. If all moves lead to positions classified
      // as WIN, the position is classified as WIN, otherwise the current position is
      // classified as UNKNOWN.
-     constexpr Color  Them = (Us == WHITE ? BLACK : WHITE);
-     constexpr Result Good = (Us == WHITE ? WIN   : DRAW);
-     constexpr Result Bad  = (Us == WHITE ? DRAW  : WIN);
+     const Result Good = (stm == WHITE ? WIN   : DRAW);
+     const Result Bad  = (stm == WHITE ? DRAW  : WIN);
  
      Result r = INVALID;
-     Bitboard b = PseudoAttacks[Us][KING][ksq[Us]];
 -    Bitboard b = PseudoAttacks[KING][ksq[stm]];
++    Bitboard b = PseudoAttacks[stm][KING][ksq[stm]];
  
      while (b)
-         r |= Us == WHITE ? db[index(Them, ksq[Them]  , pop_lsb(&b), psq)]
-                          : db[index(Them, pop_lsb(&b), ksq[Them]  , psq)];
+         r |= stm == WHITE ? db[index(BLACK, ksq[BLACK] , pop_lsb(&b), psq)]
+                           : db[index(WHITE, pop_lsb(&b),  ksq[WHITE], psq)];
  
-     if (Us == WHITE)
+     if (stm == WHITE)
      {
          if (rank_of(psq) < RANK_7)      // Single push
-             r |= db[index(Them, ksq[Them], ksq[Us], psq + NORTH)];
+             r |= db[index(BLACK, ksq[BLACK], ksq[WHITE], psq + NORTH)];
  
          if (   rank_of(psq) == RANK_2   // Double push
-             && psq + NORTH != ksq[Us]
-             && psq + NORTH != ksq[Them])
-             r |= db[index(Them, ksq[Them], ksq[Us], psq + NORTH + NORTH)];
+             && psq + NORTH != ksq[WHITE]
+             && psq + NORTH != ksq[BLACK])
+             r |= db[index(BLACK, ksq[BLACK], ksq[WHITE], psq + NORTH + NORTH)];
      }
  
      return result = r & Good  ? Good  : r & UNKNOWN ? UNKNOWN : Bad;
diff --cc src/bitboard.h
@@@ -176,15 -129,8 +176,15 @@@ constexpr bool more_than_one(Bitboard b
    return b & (b - 1);
  }
  
 +/// board_size_bb() returns a bitboard representing all the squares
 +/// on a board with given size.
 +
 +inline Bitboard board_size_bb(File f, Rank r) {
 +  return BoardSizeBB[f][r];
 +}
 +
- inline bool opposite_colors(Square s1, Square s2) {
-   return bool(DarkSquares & s1) != bool(DarkSquares & s2);
+ constexpr bool opposite_colors(Square s1, Square s2) {
+   return (s1 + rank_of(s1) + s2 + rank_of(s2)) & 1;
  }
  
  
diff --cc src/misc.cpp
Simple merge
@@@ -1251,11 -740,9 +1251,9 @@@ void Position::do_move(Move m, StateInf
  
                assert(pc == make_piece(us, PAWN));
                assert(to == st->epSquare);
 -              assert(relative_rank(us, to) == RANK_6);
 +              assert(relative_rank(~us, to, max_rank()) == Rank(double_step_rank() + 1));
                assert(piece_on(to) == NO_PIECE);
                assert(piece_on(capsq) == make_piece(them, PAWN));
-               board[capsq] = NO_PIECE; // Not done by remove_piece()
            }
  
            st->pawnKey ^= Zobrist::psq[captured][capsq];
            st->nonPawnMaterial[them] -= PieceValue[MG][captured];
  
        // Update board and piece lists
 +      bool capturedPromoted = is_promoted(capsq);
 +      Piece unpromotedCaptured = unpromoted_piece_on(capsq);
-       remove_piece(captured, capsq);
+       remove_piece(capsq);
 -
+       if (type_of(m) == ENPASSANT)
+           board[capsq] = NO_PIECE;
 +      if (captures_to_hand())
 +      {
 +          Piece pieceToHand = !capturedPromoted || drop_loop() ? ~captured
 +                             : unpromotedCaptured ? ~unpromotedCaptured
 +                                                  : make_piece(~color_of(captured), PAWN);
 +          add_to_hand(pieceToHand);
 +          k ^=  Zobrist::inHand[pieceToHand][pieceCountInHand[color_of(pieceToHand)][type_of(pieceToHand)] - 1]
 +              ^ Zobrist::inHand[pieceToHand][pieceCountInHand[color_of(pieceToHand)][type_of(pieceToHand)]];
 +      }
  
        // Update material hash key and prefetch access to materialTable
        k ^= Zobrist::psq[captured][capsq];
    }
  
    // Move the piece. The tricky Chess960 castling is handled earlier
 -  if (type_of(m) != CASTLING)
 +  if (type_of(m) == DROP)
 +  {
 +      drop_piece(make_piece(us, in_hand_piece_type(m)), pc, to);
 +      st->materialKey ^= Zobrist::psq[pc][pieceCount[pc]-1];
 +      if (type_of(pc) != PAWN)
 +          st->nonPawnMaterial[us] += PieceValue[MG][pc];
 +      // Set castling rights for dropped king or rook
 +      if (castling_dropped_piece() && rank_of(to) == castling_rank(us))
 +      {
 +          if (type_of(pc) == KING && file_of(to) == FILE_E)
 +          {
 +              Bitboard castling_rooks =  pieces(us, castling_rook_piece())
 +                                       & rank_bb(castling_rank(us))
 +                                       & (file_bb(FILE_A) | file_bb(max_file()));
 +              while (castling_rooks)
 +                  set_castling_right(us, pop_lsb(&castling_rooks));
 +          }
 +          else if (type_of(pc) == castling_rook_piece())
 +          {
 +              if (   (file_of(to) == FILE_A || file_of(to) == max_file())
 +                  && piece_on(make_square(FILE_E, castling_rank(us))) == make_piece(us, KING))
 +                  set_castling_right(us, to);
 +          }
 +      }
 +  }
 +  else if (type_of(m) != CASTLING)
-       move_piece(pc, from, to);
+       move_piece(from, to);
  
    // If the moving piece is a pawn do some special extra work
    if (type_of(pc) == PAWN)
            k ^= Zobrist::enpassant[file_of(st->epSquare)];
        }
  
 -      else if (type_of(m) == PROMOTION)
 +      else if (type_of(m) == PROMOTION || type_of(m) == PIECE_PROMOTION)
        {
 -          Piece promotion = make_piece(us, promotion_type(m));
 +          Piece promotion = make_piece(us, type_of(m) == PROMOTION ? promotion_type(m) : promoted_piece_type(PAWN));
  
 -          assert(relative_rank(us, to) == RANK_8);
 -          assert(type_of(promotion) >= KNIGHT && type_of(promotion) <= QUEEN);
 +          assert(relative_rank(us, to, max_rank()) >= promotion_rank() || sittuyin_promotion());
 +          assert(type_of(promotion) >= KNIGHT && type_of(promotion) < KING);
  
-           remove_piece(pc, to);
+           remove_piece(to);
 -          put_piece(promotion, to);
 +          put_piece(promotion, to, true, type_of(m) == PIECE_PROMOTION ? pc : NO_PIECE);
  
            // Update hash keys
            k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[promotion][to];
        // Reset rule 50 draw counter
        st->rule50 = 0;
    }
 +  else if (type_of(m) == PIECE_PROMOTION)
 +  {
 +      Piece promotion = make_piece(us, promoted_piece_type(type_of(pc)));
 +
-       remove_piece(pc, to);
++      remove_piece(to);
 +      put_piece(promotion, to, true, pc);
 +
 +      // Update hash keys
 +      k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[promotion][to];
 +      st->materialKey ^=  Zobrist::psq[promotion][pieceCount[promotion]-1]
 +                        ^ Zobrist::psq[pc][pieceCount[pc]];
 +
 +      // Update material
 +      st->nonPawnMaterial[us] += PieceValue[MG][promotion] - PieceValue[MG][pc];
 +  }
 +  else if (type_of(m) == PIECE_DEMOTION)
 +  {
 +      Piece demotion = unpromoted_piece_on(to);
 +
-       remove_piece(pc, to);
++      remove_piece(to);
 +      put_piece(demotion, to);
 +
 +      // Update hash keys
 +      k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[demotion][to];
 +      st->materialKey ^=  Zobrist::psq[demotion][pieceCount[demotion]-1]
 +                        ^ Zobrist::psq[pc][pieceCount[pc]];
 +
 +      // Update material
 +      st->nonPawnMaterial[us] += PieceValue[MG][demotion] - PieceValue[MG][pc];
 +  }
  
    // Set capture piece
    st->capturedPiece = captured;
@@@ -1494,44 -876,19 +1494,44 @@@ void Position::undo_move(Move m) 
    Square to = to_sq(m);
    Piece pc = piece_on(to);
  
 -  assert(empty(from) || type_of(m) == CASTLING);
 +  assert(type_of(m) == DROP || empty(from) || type_of(m) == CASTLING || is_gating(m)
 +         || (type_of(m) == PROMOTION && sittuyin_promotion())
 +         || (is_pass(m) && king_pass()));
    assert(type_of(st->capturedPiece) != KING);
  
 +  // Remove gated piece
 +  if (is_gating(m))
 +  {
 +      Piece gating_piece = make_piece(us, gating_type(m));
-       remove_piece(gating_piece, gating_square(m));
++      remove_piece(gating_square(m));
 +      add_to_hand(gating_piece);
 +      st->gatesBB[us] |= gating_square(m);
 +  }
 +
    if (type_of(m) == PROMOTION)
    {
 -      assert(relative_rank(us, to) == RANK_8);
 +      assert(relative_rank(us, to, max_rank()) >= promotion_rank() || sittuyin_promotion());
        assert(type_of(pc) == promotion_type(m));
 -      assert(type_of(pc) >= KNIGHT && type_of(pc) <= QUEEN);
 +      assert(type_of(pc) >= KNIGHT && type_of(pc) < KING);
  
-       remove_piece(pc, to);
+       remove_piece(to);
        pc = make_piece(us, PAWN);
        put_piece(pc, to);
    }
 +  else if (type_of(m) == PIECE_PROMOTION)
 +  {
 +      Piece unpromotedPiece = unpromoted_piece_on(to);
-       remove_piece(pc, to);
++      remove_piece(to);
 +      pc = unpromotedPiece;
 +      put_piece(pc, to);
 +  }
 +  else if (type_of(m) == PIECE_DEMOTION)
 +  {
-       remove_piece(pc, to);
++      remove_piece(to);
 +      Piece unpromotedPc = pc;
 +      pc = make_piece(us, promoted_piece_type(type_of(pc)));
 +      put_piece(pc, to, true, unpromotedPc);
 +  }
  
    if (type_of(m) == CASTLING)
    {
    }
    else
    {
 -      move_piece(to, from); // Put the piece back at the source square
 +      if (type_of(m) == DROP)
-           undrop_piece(make_piece(us, in_hand_piece_type(m)), pc, to); // Remove the dropped piece
++          undrop_piece(make_piece(us, in_hand_piece_type(m)), to); // Remove the dropped piece
 +      else
-           move_piece(pc, to, from); // Put the piece back at the source square
++          move_piece(to, from); // Put the piece back at the source square
  
        if (st->capturedPiece)
        {
@@@ -1583,17 -933,15 +1583,17 @@@ void Position::do_castling(Color us, Sq
  
    bool kingSide = to > from;
    rfrom = to; // Castling is encoded as "king captures friendly rook"
 -  rto = relative_square(us, kingSide ? SQ_F1 : SQ_D1);
 -  to = relative_square(us, kingSide ? SQ_G1 : SQ_C1);
 +  to = make_square(kingSide ? castling_kingside_file() : castling_queenside_file(), castling_rank(us));
 +  rto = to + (kingSide ? WEST : EAST);
  
    // Remove both pieces first since squares could overlap in Chess960
 +  Piece castlingKingPiece = piece_on(Do ? from : to);
 +  Piece castlingRookPiece = piece_on(Do ? rfrom : rto);
-   remove_piece(castlingKingPiece, Do ? from : to);
-   remove_piece(castlingRookPiece, Do ? rfrom : rto);
+   remove_piece(Do ? from : to);
+   remove_piece(Do ? rfrom : rto);
 -  board[Do ? from : to] = board[Do ? rfrom : rto] = NO_PIECE; // Since remove_piece doesn't do this for us
 -  put_piece(make_piece(us, KING), Do ? to : from);
 -  put_piece(make_piece(us, ROOK), Do ? rto : rfrom);
 +  board[Do ? from : to] = board[Do ? rfrom : rto] = NO_PIECE; // Since remove_piece doesn't do it for us
 +  put_piece(castlingKingPiece, Do ? to : from);
 +  put_piece(castlingRookPiece, Do ? rto : rfrom);
  }
  
  
diff --cc src/position.h
@@@ -277,9 -173,9 +277,9 @@@ private
    void set_check_info(StateInfo* si) const;
  
    // Other helpers
 -  void put_piece(Piece pc, Square s);
 +  void put_piece(Piece pc, Square s, bool isPromoted = false, Piece unpromotedPc = NO_PIECE);
-   void remove_piece(Piece pc, Square s);
-   void move_piece(Piece pc, Square from, Square to);
+   void remove_piece(Square s);
+   void move_piece(Square from, Square to);
    template<bool Do>
    void do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto);
  
    Score psq;
    Thread* thisThread;
    StateInfo* st;
 +
 +  // variant-specific
 +  const Variant* var;
    bool chess960;
 +  int pieceCountInHand[COLOR_NB][PIECE_TYPE_NB];
 +  Bitboard promotedPieces;
 +  void add_to_hand(Piece pc);
 +  void remove_from_hand(Piece pc);
 +  void drop_piece(Piece pc_hand, Piece pc_drop, Square s);
-   void undrop_piece(Piece pc_hand, Piece pc_drop, Square s);
++  void undrop_piece(Piece pc_hand, Square s);
  };
  
  namespace PSQT {
@@@ -1022,12 -410,9 +1022,12 @@@ inline void Position::put_piece(Piece p
    pieceList[pc][index[s]] = s;
    pieceCount[make_piece(color_of(pc), ALL_PIECES)]++;
    psq += PSQT::psq[pc][s];
 +  if (isPromoted)
 +      promotedPieces |= s;
 +  unpromotedBoard[s] = unpromotedPc;
  }
  
- inline void Position::remove_piece(Piece pc, Square s) {
+ inline void Position::remove_piece(Square s) {
  
    // WARNING: This is not a reversible operation. If we remove a piece in
    // do_move() and then replace it in undo_move() we will put it at the end of
    pieceList[pc][pieceCount[pc]] = SQ_NONE;
    pieceCount[make_piece(color_of(pc), ALL_PIECES)]--;
    psq -= PSQT::psq[pc][s];
 +  promotedPieces -= s;
 +  unpromotedBoard[s] = NO_PIECE;
  }
  
- inline void Position::move_piece(Piece pc, Square from, Square to) {
+ inline void Position::move_piece(Square from, Square to) {
  
    // index[from] is not updated and becomes stale. This works as long as index[]
    // is accessed just by known occupied squares.
+   Piece pc = board[from];
 -  Bitboard fromTo = from | to;
 +  Bitboard fromTo = square_bb(from) ^ to; // from == to needs to cancel out
    byTypeBB[ALL_PIECES] ^= fromTo;
    byTypeBB[type_of(pc)] ^= fromTo;
    byColorBB[color_of(pc)] ^= fromTo;
@@@ -1070,69 -451,4 +1072,69 @@@ inline void Position::do_move(Move m, S
    do_move(m, newSt, gives_check(m));
  }
  
 +inline int Position::count_in_hand(Color c, PieceType pt) const {
 +  return pieceCountInHand[c][pt];
 +}
 +
 +inline int Position::count_with_hand(Color c, PieceType pt) const {
 +  return pieceCount[make_piece(c, pt)] + pieceCountInHand[c][pt];
 +}
 +
 +inline bool Position::bikjang() const {
 +  return st->bikjang;
 +}
 +
 +inline Value Position::material_counting_result() const {
 +  auto weigth_count = [this](PieceType pt, int v){ return v * (count(WHITE, pt) - count(BLACK, pt)); };
 +  int materialCount;
 +  Value result;
 +  switch (var->materialCounting)
 +  {
 +  case JANGGI_MATERIAL:
 +      materialCount =  weigth_count(ROOK, 13)
 +                     + weigth_count(JANGGI_CANNON, 7)
 +                     + weigth_count(HORSE, 5)
 +                     + weigth_count(JANGGI_ELEPHANT, 3)
 +                     + weigth_count(WAZIR, 3)
 +                     + weigth_count(SOLDIER, 2)
 +                     - 1;
 +      result = materialCount > 0 ? VALUE_MATE : -VALUE_MATE;
 +      break;
 +  case UNWEIGHTED_MATERIAL:
 +      result =  count(WHITE, ALL_PIECES) > count(BLACK, ALL_PIECES) ?  VALUE_MATE
 +              : count(WHITE, ALL_PIECES) < count(BLACK, ALL_PIECES) ? -VALUE_MATE
 +                                                                    :  VALUE_DRAW;
 +      break;
 +  default:
 +      assert(false);
 +      result = VALUE_DRAW;
 +  }
 +  return sideToMove == WHITE ? result : -result;
 +}
 +
 +inline void Position::add_to_hand(Piece pc) {
 +  pieceCountInHand[color_of(pc)][type_of(pc)]++;
 +  pieceCountInHand[color_of(pc)][ALL_PIECES]++;
 +  psq += PSQT::psq[pc][SQ_NONE];
 +}
 +
 +inline void Position::remove_from_hand(Piece pc) {
 +  pieceCountInHand[color_of(pc)][type_of(pc)]--;
 +  pieceCountInHand[color_of(pc)][ALL_PIECES]--;
 +  psq -= PSQT::psq[pc][SQ_NONE];
 +}
 +
 +inline void Position::drop_piece(Piece pc_hand, Piece pc_drop, Square s) {
 +  assert(pieceCountInHand[color_of(pc_hand)][type_of(pc_hand)]);
 +  put_piece(pc_drop, s, pc_drop != pc_hand, pc_drop != pc_hand ? pc_hand : NO_PIECE);
 +  remove_from_hand(pc_hand);
 +}
 +
- inline void Position::undrop_piece(Piece pc_hand, Piece pc_drop, Square s) {
-   remove_piece(pc_drop, s);
++inline void Position::undrop_piece(Piece pc_hand, Square s) {
++  remove_piece(s);
 +  board[s] = NO_PIECE;
 +  add_to_hand(pc_hand);
 +  assert(pieceCountInHand[color_of(pc_hand)][type_of(pc_hand)]);
 +}
 +
  #endif // #ifndef POSITION_H_INCLUDED