X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmovegen.cpp;h=4e01d418a58d85661061612595cd77b81c3d6132;hb=746bcb348f6aa26d112ba11f748717b80f94e6a0;hp=41f5b077f9468ba9c1181a82332542cbf799774e;hpb=76bed11f7b79d939c250c02d73d0c1e2628e7a17;p=stockfish diff --git a/src/movegen.cpp b/src/movegen.cpp index 41f5b077..4e01d418 100644 --- a/src/movegen.cpp +++ b/src/movegen.cpp @@ -135,7 +135,7 @@ namespace { /// generate_captures generates() all pseudo-legal captures and queen -/// promotions. The return value is the number of moves generated. +/// promotions. Returns a pointer to the end of the move list. MoveStack* generate_captures(const Position& pos, MoveStack* mlist) { @@ -155,7 +155,7 @@ MoveStack* generate_captures(const Position& pos, MoveStack* mlist) { /// generate_noncaptures() generates all pseudo-legal non-captures and -/// underpromotions. The return value is the number of moves generated. +/// underpromotions. Returns a pointer to the end of the move list. MoveStack* generate_noncaptures(const Position& pos, MoveStack* mlist) { @@ -177,7 +177,7 @@ MoveStack* generate_noncaptures(const Position& pos, MoveStack* mlist) { /// generate_non_capture_checks() generates all pseudo-legal non-capturing, -/// non-promoting checks. It returns the number of generated moves. +/// non-promoting checks. Returns a pointer to the end of the move list. MoveStack* generate_non_capture_checks(const Position& pos, MoveStack* mlist, Bitboard dc) { @@ -214,7 +214,7 @@ MoveStack* generate_non_capture_checks(const Position& pos, MoveStack* mlist, Bi /// generate_evasions() generates all check evasions when the side to move is /// in check. Unlike the other move generation functions, this one generates -/// only legal moves. It returns the number of generated moves. +/// only legal moves. Returns a pointer to the end of the move list. MoveStack* generate_evasions(const Position& pos, MoveStack* mlist, Bitboard pinned) { @@ -225,6 +225,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)); @@ -235,31 +237,30 @@ MoveStack* generate_evasions(const Position& pos, MoveStack* mlist, Bitboard pin // Find squares attacked by slider checkers, we will // 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 square_is_attacked(). - Bitboard checkers = pos.checkers(); - Bitboard checkersAttacks = EmptyBoardBB; - Bitboard b = checkers & pos.pieces(); + // and to be able to use attackers_to(). + 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(); + 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.piece_attacks(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 square_is_attacked() only because we - // have already removed slider checkers. - if (!pos.square_is_attacked(to, them)) + // Note that we can use attackers_to() only because we + // have already removed slider checkers attacked squares. + if (!(pos.attackers_to(to) & enemy)) (*mlist++).move = make_move(ksq, to); } @@ -275,7 +276,7 @@ MoveStack* generate_evasions(const Position& pos, MoveStack* mlist, Bitboard pin // Generate captures of the checking piece // Pawn captures - b1 = pos.pawn_attacks(them, checksq) & pos.pieces(us) & ~pinned; + b1 = pos.attacks_from(checksq, them) & pos.pieces(PAWN, us) & ~pinned; while (b1) { from = pop_1st_bit(&b1); @@ -290,9 +291,9 @@ MoveStack* generate_evasions(const Position& pos, MoveStack* mlist, Bitboard pin } // Pieces captures - b1 = ( (pos.piece_attacks(checksq) & pos.pieces(us)) - | (pos.piece_attacks(checksq) & pos.pieces(us)) - | (pos.piece_attacks(checksq) & pos.pieces(us)) ) & ~pinned; + b1 = ( (pos.attacks_from(checksq) & pos.pieces(KNIGHT, us)) + | (pos.attacks_from(checksq) & pos.pieces(BISHOP, QUEEN, us)) + | (pos.attacks_from(checksq) & pos.pieces(ROOK, QUEEN, us)) ) & ~pinned; while (b1) { @@ -300,15 +301,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() | pos.pieces() | pos.pieces())) + // 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); @@ -323,10 +323,10 @@ MoveStack* generate_evasions(const Position& pos, MoveStack* mlist, Bitboard pin // check. If pos.ep_square() is set, the last move made must have been // a double pawn push. If, furthermore, the checking piece is a pawn, // an en passant check evasion may be possible. - if (pos.ep_square() != SQ_NONE && (checkers & pos.pieces(them))) + if (pos.ep_square() != SQ_NONE && (checkers & pos.pieces(PAWN, them))) { to = pos.ep_square(); - b1 = pos.pawn_attacks(them, to) & pos.pieces(us); + b1 = pos.attacks_from(to, them) & pos.pieces(PAWN, us); // The checking pawn cannot be a discovered (bishop) check candidate // otherwise we were in check also before last double push move. @@ -441,7 +441,7 @@ bool move_is_legal(const Position& pos, const Move m, Bitboard pinned) { // is occupied or under attack. for (s = Min(from, g1); s <= Max(from, g1); s++) if ( (s != from && s != to && !pos.square_is_empty(s)) - || pos.square_is_attacked(s, them)) + ||(pos.attackers_to(s) & pos.pieces_of_color(them))) illegal = true; // Check if any of the squares between king and rook @@ -472,7 +472,7 @@ bool move_is_legal(const Position& pos, const Move m, Bitboard pinned) { for (s = Min(from, c1); s <= Max(from, c1); s++) if( (s != from && s != to && !pos.square_is_empty(s)) - || pos.square_is_attacked(s, them)) + ||(pos.attackers_to(s) & pos.pieces_of_color(them))) illegal = true; for (s = Min(to, d1); s <= Max(to, d1); s++) @@ -557,7 +557,7 @@ bool move_is_legal(const Position& pos, const Move m, Bitboard pinned) { } // Luckly we can handle all the other pieces in one go - return ( pos.piece_attacks_square(pos.piece_on(from), from, to) + return ( bit_is_set(pos.attacks_from(pc, from), to) && pos.pl_move_is_legal(m, pinned) && !move_is_promotion(m)); } @@ -598,7 +598,7 @@ namespace { for (int i = 0, e = pos.piece_count(us, Piece); i < e; i++) { from = pos.piece_list(us, Piece, i); - b = pos.piece_attacks(from) & target; + b = pos.attacks_from(from) & target; SERIALIZE_MOVES(b); } return mlist; @@ -616,7 +616,7 @@ namespace { if (pinned && bit_is_set(pinned, from)) continue; - b = pos.piece_attacks(from) & target; + b = pos.attacks_from(from) & target; SERIALIZE_MOVES(b); } return mlist; @@ -628,7 +628,7 @@ namespace { Bitboard b; Square from = pos.king_square(us); - b = pos.piece_attacks(from) & target; + b = pos.attacks_from(from) & target; SERIALIZE_MOVES(b); return mlist; } @@ -675,7 +675,7 @@ namespace { const SquareDelta TDELTA_N = (Us == WHITE ? DELTA_N : DELTA_S); Square to; - Bitboard pawns = pos.pieces(Us); + Bitboard pawns = pos.pieces(PAWN, Us); Bitboard enemyPieces = pos.pieces_of_color(opposite_color(Us)); bool possiblePromotion = (pawns & TRank7BB); @@ -700,7 +700,7 @@ namespace { assert(Us != WHITE || square_rank(pos.ep_square()) == RANK_6); assert(Us != BLACK || square_rank(pos.ep_square()) == RANK_3); - Bitboard b1 = pawns & pos.pawn_attacks(Them, pos.ep_square()); + Bitboard b1 = pawns & pos.attacks_from(pos.ep_square(), Them); assert(b1 != EmptyBoardBB); while (b1) @@ -725,7 +725,7 @@ namespace { Bitboard b1, b2; Square to; - Bitboard pawns = pos.pieces(Us); + Bitboard pawns = pos.pieces(PAWN, Us); Bitboard emptySquares = pos.empty_squares(); if (pawns & TRank7BB) // There is some promotion candidate ? @@ -786,7 +786,7 @@ namespace { Square to; Bitboard b1, b2, b3; - Bitboard pawns = pos.pieces(Us); + Bitboard pawns = pos.pieces(PAWN, Us); if (dc & pawns) { @@ -819,11 +819,11 @@ namespace { // Direct checks, single pawn pushes Bitboard empty = pos.empty_squares(); b2 = move_pawns(b1) & empty; - b3 = b2 & pos.pawn_attacks(Them, ksq); + b3 = b2 & pos.attacks_from(ksq, Them); SERIALIZE_MOVES_D(b3, -TDELTA_N); // Direct checks, double pawn pushes - b3 = move_pawns(b2 & TRank3BB) & empty & pos.pawn_attacks(Them, ksq); + b3 = move_pawns(b2 & TRank3BB) & empty & pos.attacks_from(ksq, Them); SERIALIZE_MOVES_D(b3, -TDELTA_N -TDELTA_N); return mlist; } @@ -832,14 +832,14 @@ namespace { MoveStack* generate_piece_checks(const Position& pos, MoveStack* mlist, Color us, Bitboard dc, Square ksq) { - Bitboard target = pos.pieces(us); + Bitboard target = pos.pieces(Piece, us); // Discovered checks Bitboard b = target & dc; while (b) { Square from = pop_1st_bit(&b); - Bitboard bb = pos.piece_attacks(from) & pos.empty_squares(); + Bitboard bb = pos.attacks_from(from) & pos.empty_squares(); if (Piece == KING) bb &= ~QueenPseudoAttacks[ksq]; @@ -850,7 +850,7 @@ namespace { b = target & ~dc; if (Piece != KING || b) { - Bitboard checkSqs = pos.piece_attacks(ksq) & pos.empty_squares(); + Bitboard checkSqs = pos.attacks_from(ksq) & pos.empty_squares(); if (!checkSqs) return mlist; @@ -862,7 +862,7 @@ namespace { || (Piece == BISHOP && !(BishopPseudoAttacks[from] & checkSqs))) continue; - Bitboard bb = pos.piece_attacks(from) & checkSqs; + Bitboard bb = pos.attacks_from(from) & checkSqs; SERIALIZE_MOVES(bb); } } @@ -881,7 +881,7 @@ namespace { Square to; // Find non-pinned pawns and push them one square - Bitboard b1 = move_pawns(pos.pieces(Us) & ~pinned); + Bitboard b1 = move_pawns(pos.pieces(PAWN, Us) & ~pinned); // We don't have to AND with empty squares here, // because the blocking squares will always be empty. @@ -942,7 +942,7 @@ namespace { // It is a bit complicated to correctly handle Chess960 for (s = Min(ksq, s1); s <= Max(ksq, s1); s++) if ( (s != ksq && s != rsq && pos.square_is_occupied(s)) - || pos.square_is_attacked(s, them)) + ||(pos.attackers_to(s) & pos.pieces_of_color(them))) illegal = true; for (s = Min(rsq, s2); s <= Max(rsq, s2); s++)