X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fposition.cpp;h=fb17f209e3e4d24adeb9a45542f77f0b4fa8a3ba;hp=45d0147aef1f2c6d4b244ef8ae261ebe36bc4d7a;hb=66d5c13a88f041247adf2ba62acdf936a6d6224e;hpb=2f01d67a925e01508b4f3ae3bdc1c44d14b85c8e diff --git a/src/position.cpp b/src/position.cpp index 45d0147a..fb17f209 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -51,6 +51,7 @@ Key Position::zobEp[64]; Key Position::zobCastle[16]; Key Position::zobMaterial[2][8][16]; Key Position::zobSideToMove; +Key Position::zobExclusion; Score Position::PieceSquareTable[16][64]; @@ -203,11 +204,16 @@ void Position::from_fen(const string& fen) { while (fen[i] == ' ') i++; - // En passant square + // En passant square -- ignore if no capture is possible if ( i <= fen.length() - 2 && (fen[i] >= 'a' && fen[i] <= 'h') && (fen[i+1] == '3' || fen[i+1] == '6')) - st->epSquare = square_from_string(fen.substr(i, 2)); + { + Square fenEpSquare = square_from_string(fen.substr(i, 2)); + Color them = opposite_color(sideToMove); + if (attacks_from(fenEpSquare, them) & this->pieces(PAWN, sideToMove)) + st->epSquare = square_from_string(fen.substr(i, 2)); + } // Various initialisation for (Square sq = SQ_A1; sq <= SQ_H8; sq++) @@ -338,21 +344,20 @@ void Position::copy(const Position& pos) { /// king) pieces for the given color and for the given pinner type. Or, when /// template parameter FindPinned is false, the pieces of the given color /// candidate for a discovery check against the enemy king. -/// Note that checkersBB bitboard must be already updated. +/// Bitboard checkersBB must be already updated when looking for pinners. template Bitboard Position::hidden_checkers(Color c) const { - Bitboard pinners, result = EmptyBoardBB; + Bitboard result = EmptyBoardBB; + Bitboard pinners = pieces_of_color(FindPinned ? opposite_color(c) : c); // Pinned pieces protect our king, dicovery checks attack // the enemy king. Square ksq = king_square(FindPinned ? c : opposite_color(c)); - // Pinners are sliders, not checkers, that give check when - // candidate pinned is removed. - pinners = (pieces(ROOK, QUEEN, FindPinned ? opposite_color(c) : c) & RookPseudoAttacks[ksq]) - | (pieces(BISHOP, QUEEN, FindPinned ? opposite_color(c) : c) & BishopPseudoAttacks[ksq]); + // Pinners are sliders, not checkers, that give check when candidate pinned is removed + pinners &= (pieces(ROOK, QUEEN) & RookPseudoAttacks[ksq]) | (pieces(BISHOP, QUEEN) & BishopPseudoAttacks[ksq]); if (FindPinned && pinners) pinners &= ~st->checkersBB; @@ -373,7 +378,8 @@ Bitboard Position::hidden_checkers(Color c) const { /// Position:pinned_pieces() returns a bitboard of all pinned (against the -/// king) pieces for the given color. +/// king) pieces for the given color. Note that checkersBB bitboard must +/// be already updated. Bitboard Position::pinned_pieces(Color c) const { @@ -383,7 +389,8 @@ Bitboard Position::pinned_pieces(Color c) const { /// Position:discovered_check_candidates() returns a bitboard containing all /// pieces for the given side which are candidates for giving a discovered -/// check. +/// check. Contrary to pinned_pieces() here there is no need of checkersBB +/// to be already updated. Bitboard Position::discovered_check_candidates(Color c) const { @@ -647,51 +654,17 @@ bool Position::move_is_check(Move m, const CheckInfo& ci) const { } -/// Position::update_checkers() udpates chekers info given the move. It is called -/// in do_move() and is faster then find_checkers(). - -template -inline void Position::update_checkers(Bitboard* pCheckersBB, Square ksq, Square from, - Square to, Bitboard dcCandidates) { - - const bool Bishop = (Piece == QUEEN || Piece == BISHOP); - const bool Rook = (Piece == QUEEN || Piece == ROOK); - const bool Slider = Bishop || Rook; - - // Direct checks - if ( ( (Bishop && bit_is_set(BishopPseudoAttacks[ksq], to)) - || (Rook && bit_is_set(RookPseudoAttacks[ksq], to))) - && bit_is_set(attacks_from(ksq), to)) // slow, try to early skip - set_bit(pCheckersBB, to); - - else if ( Piece != KING - && !Slider - && bit_is_set(Piece == PAWN ? attacks_from(ksq, opposite_color(sideToMove)) - : attacks_from(ksq), to)) - set_bit(pCheckersBB, to); - - // Discovery checks - if (Piece != QUEEN && bit_is_set(dcCandidates, from)) - { - if (Piece != ROOK) - (*pCheckersBB) |= (attacks_from(ksq) & pieces(ROOK, QUEEN, side_to_move())); - - if (Piece != BISHOP) - (*pCheckersBB) |= (attacks_from(ksq) & pieces(BISHOP, QUEEN, side_to_move())); - } -} - - /// Position::do_move() makes a move, and saves all information necessary /// to a StateInfo object. The move is assumed to be legal. /// Pseudo-legal moves should be filtered out before this function is called. void Position::do_move(Move m, StateInfo& newSt) { - do_move(m, newSt, discovered_check_candidates(side_to_move())); + CheckInfo ci(*this); + do_move(m, newSt, ci, move_is_check(m, ci)); } -void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) { +void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveIsCheck) { assert(is_ok()); assert(move_is_ok(m)); @@ -705,7 +678,7 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) { Key pawnKey, materialKey; int castleRights, rule50, pliesFromNull; Square epSquare; - Value value; + Score value; Value npMaterial[2]; }; @@ -860,21 +833,27 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) { st->key = key; // Update checkers bitboard, piece must be already moved - if (ep | pm) - st->checkersBB = attackers_to(king_square(them)) & pieces_of_color(us); - else + st->checkersBB = EmptyBoardBB; + + if (moveIsCheck) { - st->checkersBB = EmptyBoardBB; - Square ksq = king_square(them); - switch (pt) + if (ep | pm) + st->checkersBB = attackers_to(king_square(them)) & pieces_of_color(us); + else { - case PAWN: update_checkers(&(st->checkersBB), ksq, from, to, dcCandidates); break; - case KNIGHT: update_checkers(&(st->checkersBB), ksq, from, to, dcCandidates); break; - case BISHOP: update_checkers(&(st->checkersBB), ksq, from, to, dcCandidates); break; - case ROOK: update_checkers(&(st->checkersBB), ksq, from, to, dcCandidates); break; - case QUEEN: update_checkers(&(st->checkersBB), ksq, from, to, dcCandidates); break; - case KING: update_checkers(&(st->checkersBB), ksq, from, to, dcCandidates); break; - default: assert(false); break; + // Direct checks + if (bit_is_set(ci.checkSq[pt], to)) + st->checkersBB = SetMaskBB[to]; + + // Discovery checks + if (ci.dcCandidates && bit_is_set(ci.dcCandidates, from)) + { + if (pt != ROOK) + st->checkersBB |= (attacks_from(ci.ksq) & pieces(ROOK, QUEEN, us)); + + if (pt != BISHOP) + st->checkersBB |= (attacks_from(ci.ksq) & pieces(BISHOP, QUEEN, us)); + } } } @@ -997,7 +976,7 @@ void Position::do_castle_move(Move m) { set_bit(&(byColorBB[us]), rto); set_bit(&(byTypeBB[ROOK]), rto); set_bit(&(byTypeBB[0]), rto); // HACK: byTypeBB[0] == occupied squares - + // Update board array Piece king = piece_of_color_and_type(us, KING); Piece rook = piece_of_color_and_type(us, ROOK); @@ -1182,7 +1161,7 @@ void Position::undo_castle_move(Move m) { assert(piece_on(kto) == piece_of_color_and_type(us, KING)); assert(piece_on(rto) == piece_of_color_and_type(us, ROOK)); - + // Remove pieces from destination squares: clear_bit(&(byColorBB[us]), kto); clear_bit(&(byTypeBB[KING]), kto); @@ -1190,7 +1169,7 @@ void Position::undo_castle_move(Move m) { clear_bit(&(byColorBB[us]), rto); clear_bit(&(byTypeBB[ROOK]), rto); clear_bit(&(byTypeBB[0]), rto); // HACK: byTypeBB[0] == occupied squares - + // Put pieces on source squares: set_bit(&(byColorBB[us]), kfrom); set_bit(&(byTypeBB[KING]), kfrom); @@ -1765,6 +1744,8 @@ void Position::init_zobrist() { for (int i = 0; i < 16; i++) zobMaterial[0][KING][i] = zobMaterial[1][KING][i] = Key(0ULL); + + zobExclusion = genrand_int64(); }