From: Fabian Fichter Date: Sat, 26 Jun 2021 14:04:59 +0000 (+0200) Subject: Merge official-stockfish/master X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=e17644ce4993085646acf3d67372ae63641ae393;p=fairystockfish.git Merge official-stockfish/master bench: 5173306 --- e17644ce4993085646acf3d67372ae63641ae393 diff --cc src/movegen.cpp index b85922f,bd9d0b6..af97971 --- a/src/movegen.cpp +++ b/src/movegen.cpp @@@ -120,10 -61,10 +120,10 @@@ namespace Bitboard emptySquares; Bitboard pawnsOn7 = pos.pieces(Us, PAWN) & TRank7BB; - Bitboard pawnsNotOn7 = pos.pieces(Us, PAWN) & ~TRank7BB; + Bitboard pawnsNotOn7 = pos.pieces(Us, PAWN) & (pos.mandatory_pawn_promotion() ? ~TRank7BB : AllSquares); - Bitboard enemies = (Type == EVASIONS ? pos.checkers(): - Type == CAPTURES ? target : pos.pieces(Them)); + Bitboard enemies = (Type == EVASIONS ? pos.checkers() + : Type == CAPTURES ? target : pos.pieces(Them)); // Single and double pawn pushes, no promotions if (Type != CAPTURES) @@@ -264,64 -175,23 +264,62 @@@ } - template - ExtMove* generate_moves(const Position& pos, ExtMove* moveList, PieceType Pt, Bitboard piecesToMove, Bitboard target) { - template - ExtMove* generate_moves(const Position& pos, ExtMove* moveList, Bitboard target) { ++ template ++ ExtMove* generate_moves(const Position& pos, ExtMove* moveList, PieceType Pt, Bitboard target) { - static_assert(Pt != KING && Pt != PAWN, "Unsupported piece type in generate_moves()"); + assert(Pt != KING && Pt != PAWN); - Color us = pos.side_to_move(); - - Bitboard bb = piecesToMove & pos.pieces(Pt); + Bitboard bb = pos.pieces(Us, Pt); while (bb) { Square from = pop_lsb(bb); - Bitboard b1 = ( (pos.attacks_from(us, Pt, from) & pos.pieces()) - | (pos.moves_from(us, Pt, from) & ~pos.pieces())) & target; - Bitboard b = attacks_bb(from, pos.pieces()) & target; - if (Checks && (Pt == QUEEN || !(pos.blockers_for_king(~Us) & from))) - b &= pos.check_squares(Pt); ++ Bitboard b1 = ( (pos.attacks_from(Us, Pt, from) & pos.pieces()) ++ | (pos.moves_from(Us, Pt, from) & ~pos.pieces())) & target; + PieceType promPt = pos.promoted_piece_type(Pt); - Bitboard b2 = promPt && (!pos.promotion_limit(promPt) || pos.promotion_limit(promPt) > pos.count(us, promPt)) ? b1 : Bitboard(0); ++ Bitboard b2 = promPt && (!pos.promotion_limit(promPt) || pos.promotion_limit(promPt) > pos.count(Us, promPt)) ? b1 : Bitboard(0); + Bitboard b3 = pos.piece_demotion() && pos.is_promoted(from) ? b1 : Bitboard(0); - while (b) - *moveList++ = make_move(from, pop_lsb(b)); + if (Checks) + { + b1 &= pos.check_squares(Pt); + if (b2) + b2 &= pos.check_squares(pos.promoted_piece_type(Pt)); + if (b3) + b3 &= pos.check_squares(type_of(pos.unpromoted_piece_on(from))); + } + + // Restrict target squares considering promotion zone + if (b2 | b3) + { - Bitboard promotion_zone = zone_bb(us, pos.promotion_rank(), pos.max_rank()); ++ Bitboard promotion_zone = zone_bb(Us, pos.promotion_rank(), pos.max_rank()); + if (pos.mandatory_piece_promotion()) + b1 &= (promotion_zone & from ? Bitboard(0) : ~promotion_zone) | (pos.piece_promotion_on_capture() ? ~pos.pieces() : Bitboard(0)); + // Exclude quiet promotions/demotions + if (pos.piece_promotion_on_capture()) + { + b2 &= pos.pieces(); + b3 &= pos.pieces(); + } + // Consider promotions/demotions into promotion zone + if (!(promotion_zone & from)) + { + b2 &= promotion_zone; + b3 &= promotion_zone; + } + } + + while (b1) - moveList = make_move_and_gating(pos, moveList, us, from, pop_lsb(b1)); ++ moveList = make_move_and_gating(pos, moveList, Us, from, pop_lsb(b1)); + + // Shogi-style piece promotions + while (b2) + *moveList++ = make(from, pop_lsb(b2)); + + // Piece demotions + while (b3) + *moveList++ = make(from, pop_lsb(b3)); } return moveList; @@@ -334,101 -204,39 +332,91 @@@ static_assert(Type != LEGAL, "Unsupported type in generate_all()"); constexpr bool Checks = Type == QUIET_CHECKS; // Reduce template instantiations - Bitboard target, piecesToMove = pos.pieces(Us); - const Square ksq = pos.square(Us); ++ const Square ksq = pos.count(Us) ? pos.square(Us) : SQ_NONE; + Bitboard target; + - if (Type == EVASIONS && more_than_one(pos.checkers())) ++ if (Type == EVASIONS && more_than_one(pos.checkers() & ~pos.non_sliding_riders())) + goto kingMoves; // Double check, only a king move can save the day - if(Type == QUIET_CHECKS) - piecesToMove &= ~pos.blockers_for_king(~Us); + target = Type == EVASIONS ? between_bb(ksq, lsb(pos.checkers())) + : Type == NON_EVASIONS ? ~pos.pieces( Us) + : Type == CAPTURES ? pos.pieces(~Us) + : ~pos.pieces( ); // QUIETS || QUIET_CHECKS - switch (Type) ++ if (Type == EVASIONS) + { - case CAPTURES: - target = pos.pieces(~Us); - break; - case QUIETS: - case QUIET_CHECKS: - target = ~pos.pieces(); - break; - case EVASIONS: - { - if (pos.checkers() & pos.non_sliding_riders()) - { - target = ~pos.pieces(Us); - break; - } - target = between_bb(pos.square(Us), lsb(pos.checkers())); - // Leaper attacks can not be blocked - Square checksq = lsb(pos.checkers()); - if (LeaperAttacks[~Us][type_of(pos.piece_on(checksq))][checksq] & pos.square(Us)) - target = pos.checkers(); - break; - } - case NON_EVASIONS: ++ if (pos.checkers() & pos.non_sliding_riders()) + target = ~pos.pieces(Us); - break; ++ // Leaper attacks can not be blocked ++ Square checksq = lsb(pos.checkers()); ++ if (LeaperAttacks[~Us][type_of(pos.piece_on(checksq))][checksq] & pos.square(Us)) ++ target = pos.checkers(); + } ++ + target &= pos.board_bb(); + moveList = generate_pawn_moves(pos, moveList, target); - moveList = generate_moves(pos, moveList, target); - moveList = generate_moves(pos, moveList, target); - moveList = generate_moves(pos, moveList, target); - moveList = generate_moves(pos, moveList, target); + for (PieceType pt : pos.piece_types()) + if (pt != PAWN && pt != KING) - moveList = generate_moves(pos, moveList, pt, piecesToMove, target); ++ moveList = generate_moves(pos, moveList, pt, target); + // generate drops + if (pos.piece_drops() && Type != CAPTURES && (pos.count_in_hand(Us, ALL_PIECES) > 0 || pos.two_boards())) + for (PieceType pt : pos.piece_types()) + moveList = generate_drops(pos, moveList, pt, target & ~pos.pieces(~Us)); + - if (Type != QUIET_CHECKS && Type != EVASIONS && pos.count(Us)) - { - Square ksq = pos.square(Us); - Bitboard b = ( (pos.attacks_from(Us, KING, ksq) & pos.pieces()) - | (pos.moves_from(Us, KING, ksq) & ~pos.pieces())) & target; - while (b) - moveList = make_move_and_gating(pos, moveList, Us, ksq, pop_lsb(b)); - - // Passing move by king - if (pos.pass()) - *moveList++ = make(ksq, ksq); - - if ((Type != CAPTURES) && pos.can_castle(Us & ANY_CASTLING)) - for (CastlingRights cr : { Us & KING_SIDE, Us & QUEEN_SIDE } ) - if (!pos.castling_impeded(cr) && pos.can_castle(cr)) - moveList = make_move_and_gating(pos, moveList, Us,ksq, pos.castling_rook_square(cr)); - } - // Workaround for passing: Execute a non-move with any piece - else if (pos.pass() && !pos.count(Us) && pos.pieces(Us)) - *moveList++ = make(lsb(pos.pieces(Us)), lsb(pos.pieces(Us))); - + // Castling with non-king piece + if (!pos.count(Us) && Type != CAPTURES && pos.can_castle(Us & ANY_CASTLING)) + { + Square from = pos.castling_king_square(Us); + for(CastlingRights cr : { Us & KING_SIDE, Us & QUEEN_SIDE } ) + if (!pos.castling_impeded(cr) && pos.can_castle(cr)) + moveList = make_move_and_gating(pos, moveList, Us, from, pos.castling_rook_square(cr)); + } -kingMoves: - if (!Checks || pos.blockers_for_king(~Us) & ksq) + // Special moves + if (pos.cambodian_moves() && pos.gates(Us)) { - Bitboard b = attacks_bb(ksq) & (Type == EVASIONS ? ~pos.pieces(Us) : target); - if (Checks) - b &= ~attacks_bb(pos.square(~Us)); + if (Type != CAPTURES && Type != EVASIONS && (pos.pieces(Us, KING) & pos.gates(Us))) + { + Square from = pos.square(Us); + Bitboard b = PseudoAttacks[WHITE][KNIGHT][from] & rank_bb(rank_of(from + (Us == WHITE ? NORTH : SOUTH))) + & target & ~pos.pieces(); + while (b) + moveList = make_move_and_gating(pos, moveList, Us, from, pop_lsb(b)); + } + + Bitboard b = pos.pieces(Us, FERS) & pos.gates(Us); + while (b) + { + Square from = pop_lsb(b); + Square to = from + 2 * (Us == WHITE ? NORTH : SOUTH); + if (is_ok(to) && (target & to)) + moveList = make_move_and_gating(pos, moveList, Us, from, to); + } + } ++ // Workaround for passing: Execute a non-move with any piece ++ if (pos.pass() && !pos.count(Us) && pos.pieces(Us)) ++ *moveList++ = make(lsb(pos.pieces(Us)), lsb(pos.pieces(Us))); ++ ++kingMoves: ++ if (pos.count(Us) && (!Checks || pos.blockers_for_king(~Us) & ksq)) ++ { ++ Bitboard b = ( (pos.attacks_from(Us, KING, ksq) & pos.pieces()) ++ | (pos.moves_from(Us, KING, ksq) & ~pos.pieces())) & (Type == EVASIONS ? ~pos.pieces(Us) : target); + while (b) - *moveList++ = make_move(ksq, pop_lsb(b)); ++ moveList = make_move_and_gating(pos, moveList, Us, ksq, pop_lsb(b)); ++ ++ // Passing move by king ++ if (pos.pass()) ++ *moveList++ = make(ksq, ksq); + + if ((Type == QUIETS || Type == NON_EVASIONS) && pos.can_castle(Us & ANY_CASTLING)) + for (CastlingRights cr : { Us & KING_SIDE, Us & QUEEN_SIDE } ) + if (!pos.castling_impeded(cr) && pos.can_castle(cr)) - *moveList++ = make(ksq, pos.castling_rook_square(cr)); ++ moveList = make_move_and_gating(pos, moveList, Us,ksq, pos.castling_rook_square(cr)); + } + return moveList; }