X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmovegen.cpp;h=8ec7124b1095c5517fd0252dcbb40723c65a522f;hb=43ca5c926dfaf13d64d51c4085070209f4c5f452;hp=07c99bf441d996081cb941342f0f3525929e6878;hpb=e4277c06bfb783b5ec78001eeef06fa9feae033f;p=stockfish diff --git a/src/movegen.cpp b/src/movegen.cpp index 07c99bf4..8ec7124b 100644 --- a/src/movegen.cpp +++ b/src/movegen.cpp @@ -66,11 +66,8 @@ namespace { template MoveStack* generate_pawn_captures_diagonal(MoveStack* mlist, Bitboard pawns, Bitboard enemyPieces, bool promotion); - template - MoveStack* generate_pawn_noncaptures(const Position& pos, MoveStack* mlist); - - template - MoveStack* generate_pawn_checks(const Position&, Bitboard, Square, MoveStack*); + template + MoveStack* generate_pawn_noncaptures(const Position& pos, MoveStack* mlist, Bitboard dc = EmptyBoardBB, Square ksq = SQ_NONE); template inline Bitboard move_pawns(Bitboard p) { @@ -92,8 +89,8 @@ namespace { template<> inline MoveStack* generate_piece_checks(const Position& p, MoveStack* m, Color us, Bitboard dc, Square ksq) { - return (us == WHITE ? generate_pawn_checks(p, dc, ksq, m) - : generate_pawn_checks(p, dc, ksq, m)); + return (us == WHITE ? generate_pawn_noncaptures(p, m, dc, ksq) + : generate_pawn_noncaptures(p, m, dc, ksq)); } // Template generate_piece_moves() with specializations and overloads @@ -112,8 +109,8 @@ namespace { return (us == WHITE ? generate_pawn_captures(p, m) : generate_pawn_captures(p, m)); else - return (us == WHITE ? generate_pawn_noncaptures(p, m) - : generate_pawn_noncaptures(p, m)); + return (us == WHITE ? generate_pawn_noncaptures(p, m) + : generate_pawn_noncaptures(p, m)); } template @@ -225,6 +222,8 @@ MoveStack* generate_evasions(const Position& pos, MoveStack* mlist, Bitboard pin Color us = pos.side_to_move(); Color them = opposite_color(us); Square ksq = pos.king_square(us); + Bitboard sliderAttacks = EmptyBoardBB; + Bitboard checkers = pos.checkers(); assert(pos.piece_on(ksq) == piece_of_color_and_type(us, KING)); @@ -236,30 +235,28 @@ MoveStack* generate_evasions(const Position& pos, MoveStack* mlist, Bitboard pin // remove them from king evasions set so to avoid a couple // of cycles in the slow king evasions legality check loop // and to be able to use attackers_to(). - Bitboard checkers = pos.checkers(); - Bitboard checkersAttacks = EmptyBoardBB; Bitboard b = checkers & pos.pieces(BISHOP, QUEEN); while (b) { from = pop_1st_bit(&b); - checkersAttacks |= bishop_attacks_bb(from, b_noKing); + sliderAttacks |= bishop_attacks_bb(from, b_noKing); } b = checkers & pos.pieces(ROOK, QUEEN); while (b) { from = pop_1st_bit(&b); - checkersAttacks |= rook_attacks_bb(from, b_noKing); + sliderAttacks |= rook_attacks_bb(from, b_noKing); } - // Generate evasions for king - Bitboard b1 = pos.attacks_from(ksq) & ~pos.pieces_of_color(us) & ~checkersAttacks; + // Generate evasions for king, both captures and non captures + Bitboard b1 = pos.attacks_from(ksq) & ~pos.pieces_of_color(us) & ~sliderAttacks; Bitboard enemy = pos.pieces_of_color(them); while (b1) { to = pop_1st_bit(&b1); // Note that we can use attackers_to() only because we - // have already removed slider checkers. + // have already removed slider checkers attacked squares. if (!(pos.attackers_to(to) & enemy)) (*mlist++).move = make_move(ksq, to); } @@ -301,15 +298,14 @@ MoveStack* generate_evasions(const Position& pos, MoveStack* mlist, Bitboard pin (*mlist++).move = make_move(from, checksq); } - // Blocking check evasions are possible only if the checking piece is - // a slider. - if (checkers & (pos.pieces(BISHOP) | pos.pieces(ROOK) | pos.pieces(QUEEN))) + // Blocking check evasions are possible only if the checking piece is a slider + if (sliderAttacks) { Bitboard blockSquares = squares_between(checksq, ksq); assert((pos.occupied_squares() & blockSquares) == EmptyBoardBB); - if (blockSquares != EmptyBoardBB) + if (blockSquares) { mlist = generate_piece_moves(pos, mlist, us, blockSquares, pinned); mlist = generate_piece_moves(pos, mlist, us, blockSquares, pinned); @@ -713,10 +709,11 @@ namespace { return mlist; } - template - MoveStack* generate_pawn_noncaptures(const Position& pos, MoveStack* mlist) { + template + MoveStack* generate_pawn_noncaptures(const Position& pos, MoveStack* mlist, Bitboard dc, Square ksq) { // Calculate our parametrized parameters at compile time + const Color Them = (Us == WHITE ? BLACK : WHITE); const Bitboard TRank8BB = (Us == WHITE ? Rank8BB : Rank1BB); const Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB); const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB); @@ -724,17 +721,20 @@ namespace { const SquareDelta TDELTA_NW = (Us == WHITE ? DELTA_NW : DELTA_SW); const SquareDelta TDELTA_N = (Us == WHITE ? DELTA_N : DELTA_S); - Bitboard b1, b2; + Bitboard b1, b2, dcPawns1, dcPawns2; Square to; Bitboard pawns = pos.pieces(PAWN, Us); Bitboard emptySquares = pos.empty_squares(); if (pawns & TRank7BB) // There is some promotion candidate ? { - Bitboard enemyPieces = pos.pieces_of_color(opposite_color(Us)); + // When generating checks consider under-promotion moves (both captures + // and non captures) only if can give a discovery check. + Bitboard pp = GenerateChecks ? pawns & dc : pawns; + Bitboard enemyPieces = pos.pieces_of_color(opposite_color(Us)); // Underpromotion captures in the a1-h8 (a8-h1 for black) direction - b1 = move_pawns(pawns) & ~FileABB & enemyPieces & TRank8BB; + b1 = move_pawns(pp) & ~FileABB & enemyPieces & TRank8BB; while (b1) { to = pop_1st_bit(&b1); @@ -744,7 +744,7 @@ namespace { } // Underpromotion captures in the h1-a8 (h8-a1 for black) direction - b1 = move_pawns(pawns) & ~FileHBB & enemyPieces & TRank8BB; + b1 = move_pawns(pp) & ~FileHBB & enemyPieces & TRank8BB; while (b1) { to = pop_1st_bit(&b1); @@ -754,7 +754,7 @@ namespace { } // Underpromotion pawn pushes - b1 = move_pawns(pawns) & emptySquares & TRank8BB; + b1 = move_pawns(pp) & emptySquares & TRank8BB; while (b1) { to = pop_1st_bit(&b1); @@ -764,68 +764,25 @@ namespace { } } - // Single pawn pushes - b2 = b1 = move_pawns(pawns) & emptySquares & ~TRank8BB; - SERIALIZE_MOVES_D(b2, -TDELTA_N); - - // Double pawn pushes - b2 = move_pawns(b1 & TRank3BB) & emptySquares; - SERIALIZE_MOVES_D(b2, -TDELTA_N -TDELTA_N); - return mlist; - } - - - template - MoveStack* generate_pawn_checks(const Position& pos, Bitboard dc, Square ksq, MoveStack* mlist) - { - // Calculate our parametrized parameters at compile time - const Color Them = (Us == WHITE ? BLACK : WHITE); - const Bitboard TRank8BB = (Us == WHITE ? Rank8BB : Rank1BB); - const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB); - const SquareDelta TDELTA_N = (Us == WHITE ? DELTA_N : DELTA_S); - const SquareDelta TDELTA_S = (Us == WHITE ? DELTA_S : DELTA_N); - - Square to; - Bitboard b1, b2, b3; - Bitboard pawns = pos.pieces(PAWN, Us); - - if (dc & pawns) + dcPawns1 = dcPawns2 = EmptyBoardBB; + if (GenerateChecks && (dc & pawns)) { - Bitboard empty = pos.empty_squares(); - // Pawn moves which gives discovered check. This is possible only if the // pawn is not on the same file as the enemy king, because we don't // generate captures. - b1 = pawns & ~file_bb(ksq); - - // Discovered checks, single pawn pushes, no promotions - b2 = b3 = move_pawns(b1 & dc) & empty & ~TRank8BB; - SERIALIZE_MOVES_D(b3, -TDELTA_N); - - // Discovered checks, double pawn pushes - b3 = move_pawns(b2 & TRank3BB) & empty; - SERIALIZE_MOVES_D(b3, -TDELTA_N -TDELTA_N); + dcPawns1 = move_pawns(pawns & dc & ~file_bb(ksq)) & emptySquares & ~TRank8BB; + dcPawns2 = move_pawns(dcPawns1 & TRank3BB) & emptySquares; } - // Direct checks. These are possible only for pawns on neighboring files - // and in the two ranks that, after the push, are in front of the enemy king. - b1 = pawns & neighboring_files_bb(ksq) & ~dc; - - // We can get false positives if (ksq + x) is not in [0,63] range but - // is not a problem, they will be filtered out later. - b2 = b1 & (rank_bb(ksq + 2 * TDELTA_S) | rank_bb(ksq + 3 * TDELTA_S)); - if (!b2) - return mlist; - - // Direct checks, single pawn pushes - Bitboard empty = pos.empty_squares(); - b2 = move_pawns(b1) & empty; - b3 = b2 & pos.attacks_from(ksq, Them); - SERIALIZE_MOVES_D(b3, -TDELTA_N); + // Single pawn pushes + b1 = move_pawns(pawns) & emptySquares & ~TRank8BB; + b2 = GenerateChecks ? (b1 & pos.attacks_from(ksq, Them)) | dcPawns1 : b1; + SERIALIZE_MOVES_D(b2, -TDELTA_N); - // Direct checks, double pawn pushes - b3 = move_pawns(b2 & TRank3BB) & empty & pos.attacks_from(ksq, Them); - SERIALIZE_MOVES_D(b3, -TDELTA_N -TDELTA_N); + // Double pawn pushes + b1 = move_pawns(b1 & TRank3BB) & emptySquares; + b2 = GenerateChecks ? (b1 & pos.attacks_from(ksq, Them)) | dcPawns2 : b1; + SERIALIZE_MOVES_D(b2, -TDELTA_N -TDELTA_N); return mlist; } @@ -849,23 +806,20 @@ namespace { // Direct checks b = target & ~dc; - if (Piece != KING || b) + Bitboard checkSqs = pos.attacks_from(ksq) & pos.empty_squares(); + if (Piece == KING || !checkSqs) + return mlist; + + while (b) { - Bitboard checkSqs = pos.attacks_from(ksq) & pos.empty_squares(); - if (!checkSqs) - return mlist; + Square from = pop_1st_bit(&b); + if ( (Piece == QUEEN && !(QueenPseudoAttacks[from] & checkSqs)) + || (Piece == ROOK && !(RookPseudoAttacks[from] & checkSqs)) + || (Piece == BISHOP && !(BishopPseudoAttacks[from] & checkSqs))) + continue; - while (b) - { - Square from = pop_1st_bit(&b); - if ( (Piece == QUEEN && !(QueenPseudoAttacks[from] & checkSqs)) - || (Piece == ROOK && !(RookPseudoAttacks[from] & checkSqs)) - || (Piece == BISHOP && !(BishopPseudoAttacks[from] & checkSqs))) - continue; - - Bitboard bb = pos.attacks_from(from) & checkSqs; - SERIALIZE_MOVES(bb); - } + Bitboard bb = pos.attacks_from(from) & checkSqs; + SERIALIZE_MOVES(bb); } return mlist; }