From: Fabian Fichter Date: Sun, 31 May 2020 21:51:58 +0000 (+0200) Subject: Merge official-stockfish/master X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=9159613466288e4759fb1e7a0dc8c1c538ce6571;p=fairystockfish.git Merge official-stockfish/master No functional change. --- 9159613466288e4759fb1e7a0dc8c1c538ce6571 diff --cc src/bitbase.cpp index 0040f88,ed6ed20..c1819d7 --- a/src/bitbase.cpp +++ b/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 @@@ -156,27 -146,25 +151,25 @@@ // 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 index e4f7e57,d11b7e7..307dac7 --- a/src/bitboard.h +++ b/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/position.cpp index df633f8,de9722f..266d651 --- a/src/position.cpp +++ b/src/position.cpp @@@ -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]; @@@ -1264,18 -751,10 +1262,20 @@@ 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]; @@@ -1313,33 -784,8 +1313,33 @@@ } // 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) @@@ -1353,15 -798,15 +1353,15 @@@ 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]; @@@ -1379,36 -824,6 +1379,36 @@@ // 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) { @@@ -1540,10 -897,7 +1540,10 @@@ } 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 index 47302ef,e5071d5..0415312 --- a/src/position.h +++ b/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 void do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto); @@@ -299,16 -194,7 +299,16 @@@ 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 @@@ -1043,15 -429,14 +1044,16 @@@ 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