X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fmovegen.cpp;h=154e69e2207dc504c718050d310254cd9f880da0;hp=441ab70c7e0ddca02fc2475bf550cc1e1253ad8b;hb=d549497144ee2a704057e005d2bbe1fbc666ca7e;hpb=875a8079bc142ca92027b07427d72c03fe5268a5 diff --git a/src/movegen.cpp b/src/movegen.cpp index 441ab70c..154e69e2 100644 --- a/src/movegen.cpp +++ b/src/movegen.cpp @@ -32,52 +32,32 @@ (*mlist++).move = make_move(to - (d), to); } namespace { - enum CastlingSide { KING_SIDE, QUEEN_SIDE }; - template MoveStack* generate_castle(const Position& pos, MoveStack* mlist, Color us) { - const CastleRight CR[] = { Side ? WHITE_OOO : WHITE_OO, - Side ? BLACK_OOO : BLACK_OO }; - - if (!pos.can_castle(CR[us])) + if (pos.castle_impeded(us, Side) || !pos.can_castle(make_castle_right(us, Side))) return mlist; // After castling, the rook and king final positions are the same in Chess960 // as they would be in standard chess. Square kfrom = pos.king_square(us); - Square rfrom = pos.castle_rook_square(CR[us]); + Square rfrom = pos.castle_rook_square(us, Side); Square kto = relative_square(us, Side == KING_SIDE ? SQ_G1 : SQ_C1); - Square rto = relative_square(us, Side == KING_SIDE ? SQ_F1 : SQ_D1); Bitboard enemies = pos.pieces(~us); assert(!pos.in_check()); - assert(pos.piece_on(kfrom) == make_piece(us, KING)); - assert(pos.piece_on(rfrom) == make_piece(us, ROOK)); - - // Unimpeded rule: All the squares between the king's initial and final squares - // (including the final square), and all the squares between the rook's initial - // and final squares (including the final square), must be vacant except for - // the king and castling rook. - for (Square s = std::min(rfrom, rto), e = std::max(rfrom, rto); s <= e; s++) - if (s != kfrom && s != rfrom && !pos.square_is_empty(s)) - return mlist; for (Square s = std::min(kfrom, kto), e = std::max(kfrom, kto); s <= e; s++) - if ( (s != kfrom && s != rfrom && !pos.square_is_empty(s)) - ||(pos.attackers_to(s) & enemies)) + if ( s != kfrom // We are not in check + && (pos.attackers_to(s) & enemies)) return mlist; // Because we generate only legal castling moves we need to verify that // when moving the castling rook we do not discover some hidden checker. // For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1. - if (pos.is_chess960()) - { - Bitboard occ = pos.occupied_squares(); - xor_bit(&occ, rfrom); - if (pos.attackers_to(kto, occ) & enemies) + if ( pos.is_chess960() + && (pos.attackers_to(kto, pos.pieces() ^ rfrom) & enemies)) return mlist; - } (*mlist++).move = make_castle(kfrom, rfrom); @@ -121,7 +101,7 @@ namespace { // Knight-promotion is the only one that can give a direct check not // already included in the queen-promotion. - if (Type == MV_QUIET_CHECK && bit_is_set(StepAttacksBB[W_KNIGHT][to], ksq)) + if (Type == MV_QUIET_CHECK && (StepAttacksBB[W_KNIGHT][to] & ksq)) (*mlist++).move = make_promotion(to - Delta, to, KNIGHT); else (void)ksq; // Silence a warning under MSVC @@ -155,7 +135,7 @@ namespace { // Single and double pawn pushes, no promotions if (Type != MV_CAPTURE) { - emptySquares = (Type == MV_QUIET ? target : pos.empty_squares()); + emptySquares = (Type == MV_QUIET ? target : ~pos.pieces()); b1 = move_pawns(pawnsNotOn7) & emptySquares; b2 = move_pawns(b1 & TRank3BB) & emptySquares; @@ -193,7 +173,7 @@ namespace { if (pawnsOn7 && (Type != MV_EVASION || (target & TRank8BB))) { if (Type == MV_CAPTURE) - emptySquares = pos.empty_squares(); + emptySquares = ~pos.pieces(); if (Type == MV_EVASION) emptySquares &= target; @@ -219,7 +199,7 @@ namespace { // An en passant capture can be an evasion only if the checking piece // is the double pushed pawn and so is in the target. Otherwise this // is a discovery check and we are forced to do otherwise. - if (Type == MV_EVASION && !bit_is_set(target, pos.ep_square() - UP)) + if (Type == MV_EVASION && !(target & (pos.ep_square() - UP))) return mlist; b1 = pawnsNotOn7 & pos.attacks_from(pos.ep_square(), Them); @@ -246,7 +226,7 @@ namespace { if (*pl != SQ_NONE) { - target = ci.checkSq[Pt] & pos.empty_squares(); // Non capture checks only + target = ci.checkSq[Pt] & ~pos.pieces(); // Non capture checks only do { from = *pl; @@ -255,7 +235,7 @@ namespace { && !(PseudoAttacks[Pt][from] & target)) continue; - if (ci.dcCandidates && bit_is_set(ci.dcCandidates, from)) + if (ci.dcCandidates && (ci.dcCandidates & from)) continue; b = pos.attacks_from(from) & target; @@ -321,10 +301,10 @@ MoveStack* generate(const Position& pos, MoveStack* mlist) { target = pos.pieces(~us); else if (Type == MV_QUIET) - target = pos.empty_squares(); + target = ~pos.pieces(); else if (Type == MV_NON_EVASION) - target = pos.pieces(~us) | pos.empty_squares(); + target = ~pos.pieces(us); mlist = (us == WHITE ? generate_pawn_moves(pos, mlist, target) : generate_pawn_moves(pos, mlist, target)); @@ -369,7 +349,7 @@ MoveStack* generate(const Position& pos, MoveStack* mlist) { if (pt == PAWN) continue; // Will be generated togheter with direct checks - Bitboard b = pos.attacks_from(Piece(pt), from) & pos.empty_squares(); + Bitboard b = pos.attacks_from(Piece(pt), from) & ~pos.pieces(); if (pt == KING) b &= ~PseudoAttacks[QUEEN][ci.ksq]; @@ -430,7 +410,7 @@ MoveStack* generate(const Position& pos, MoveStack* mlist) { // If queen and king are far or not on a diagonal line we can safely // remove all the squares attacked in the other direction becuase are // not reachable by the king anyway. - if (squares_between(ksq, checksq) || !bit_is_set(PseudoAttacks[BISHOP][checksq], ksq)) + if (squares_between(ksq, checksq) || !(PseudoAttacks[BISHOP][checksq] & ksq)) sliderAttacks |= PseudoAttacks[QUEEN][checksq]; // Otherwise we need to use real rook attacks to check if king is safe