X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fposition.cpp;h=ed5cc43f557a940c949d379be16e1e659012f86f;hp=d3afddeb4fb1df982f15604d0f5c70eafa905e23;hb=298cf150958212e3270182644fd87f5489823b27;hpb=5d7ad47c198c54e7a91876a6d8d8488a0c23a1ba diff --git a/src/position.cpp b/src/position.cpp index d3afddeb..ed5cc43f 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -18,7 +18,6 @@ along with this program. If not, see . */ -#include #include #include // For offsetof() #include // For std::memset, std::memcmp @@ -183,7 +182,7 @@ void Position::init() { { std::swap(cuckoo[i], key); std::swap(cuckooMove[i], move); - if (move == 0) // Arrived at empty slot ? + if (move == MOVE_NONE) // Arrived at empty slot? break; i = (i == H1(key)) ? H2(key) : H1(key); // Push victim to alternative slot } @@ -339,13 +338,8 @@ void Position::set_castling_right(Color c, Square rfrom) { Square kto = relative_square(c, cs == KING_SIDE ? SQ_G1 : SQ_C1); Square rto = relative_square(c, cs == KING_SIDE ? SQ_F1 : SQ_D1); - for (Square s = std::min(rfrom, rto); s <= std::max(rfrom, rto); ++s) - if (s != kfrom && s != rfrom) - castlingPath[cr] |= s; - - for (Square s = std::min(kfrom, kto); s <= std::max(kfrom, kto); ++s) - if (s != kfrom && s != rfrom) - castlingPath[cr] |= s; + castlingPath[cr] = (between_bb(rfrom, rto) | between_bb(kfrom, kto) | rto | kto) + & ~(square_bb(kfrom) | rfrom); } @@ -463,16 +457,16 @@ const string Position::fen() const { ss << (sideToMove == WHITE ? " w " : " b "); if (can_castle(WHITE_OO)) - ss << (chess960 ? char('A' + file_of(castling_rook_square(WHITE | KING_SIDE))) : 'K'); + ss << (chess960 ? char('A' + file_of(castling_rook_square(WHITE_OO ))) : 'K'); if (can_castle(WHITE_OOO)) - ss << (chess960 ? char('A' + file_of(castling_rook_square(WHITE | QUEEN_SIDE))) : 'Q'); + ss << (chess960 ? char('A' + file_of(castling_rook_square(WHITE_OOO))) : 'Q'); if (can_castle(BLACK_OO)) - ss << (chess960 ? char('a' + file_of(castling_rook_square(BLACK | KING_SIDE))) : 'k'); + ss << (chess960 ? char('a' + file_of(castling_rook_square(BLACK_OO ))) : 'k'); if (can_castle(BLACK_OOO)) - ss << (chess960 ? char('a' + file_of(castling_rook_square(BLACK | QUEEN_SIDE))) : 'q'); + ss << (chess960 ? char('a' + file_of(castling_rook_square(BLACK_OOO))) : 'q'); if (!can_castle(ANY_CASTLING)) ss << '-'; @@ -496,14 +490,15 @@ Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners Bitboard blockers = 0; pinners = 0; - // Snipers are sliders that attack 's' when a piece is removed + // Snipers are sliders that attack 's' when a piece and other snipers are removed Bitboard snipers = ( (PseudoAttacks[ ROOK][s] & pieces(QUEEN, ROOK)) | (PseudoAttacks[BISHOP][s] & pieces(QUEEN, BISHOP))) & sliders; + Bitboard occupancy = pieces() & ~snipers; while (snipers) { Square sniperSq = pop_lsb(&snipers); - Bitboard b = between_bb(s, sniperSq) & pieces(); + Bitboard b = between_bb(s, sniperSq) & occupancy; if (b && !more_than_one(b)) { @@ -538,6 +533,7 @@ bool Position::legal(Move m) const { Color us = sideToMove; Square from = from_sq(m); + Square to = to_sq(m); assert(color_of(moved_piece(m)) == us); assert(piece_on(square(us)) == make_piece(us, KING)); @@ -548,7 +544,6 @@ bool Position::legal(Move m) const { if (type_of(m) == ENPASSANT) { Square ksq = square(us); - Square to = to_sq(m); Square capsq = to - pawn_push(us); Bitboard occupied = (pieces() ^ from ^ capsq) | to; @@ -561,16 +556,35 @@ bool Position::legal(Move m) const { && !(attacks_bb(ksq, occupied) & pieces(~us, QUEEN, BISHOP)); } - // If the moving piece is a king, check whether the destination - // square is attacked by the opponent. Castling moves are checked - // for legality during move generation. + // Castling moves generation does not check if the castling path is clear of + // enemy attacks, it is delayed at a later time: now! + if (type_of(m) == CASTLING) + { + // After castling, the rook and king final positions are the same in + // Chess960 as they would be in standard chess. + to = relative_square(us, to > from ? SQ_G1 : SQ_C1); + Direction step = to > from ? WEST : EAST; + + for (Square s = to; s != from; s += step) + if (attackers_to(s) & pieces(~us)) + return false; + + // In case of Chess960, 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. + return !chess960 + || !(attacks_bb(to, pieces() ^ to_sq(m)) & pieces(~us, ROOK, QUEEN)); + } + + // If the moving piece is a king, check whether the destination square is + // attacked by the opponent. if (type_of(piece_on(from)) == KING) - return type_of(m) == CASTLING || !(attackers_to(to_sq(m)) & pieces(~us)); + return !(attackers_to(to) & pieces(~us)); // A non-king move is legal if and only if it is not pinned or it // is moving along the ray towards or away from the king. return !(blockers_for_king(us) & from) - || aligned(from, to_sq(m), square(us)); + || aligned(from, to, square(us)); } @@ -607,7 +621,7 @@ bool Position::pseudo_legal(const Move m) const { { // We have already handled promotion moves, so destination // cannot be on the 8th/1st rank. - if (rank_of(to) == relative_rank(us, RANK_8)) + if ((Rank8BB | Rank1BB) & to) return false; if ( !(attacks_from(from, us) & pieces(~us) & to) // Not a capture @@ -1055,8 +1069,8 @@ bool Position::see_ge(Move m, Value threshold) const { stmAttackers = attackers & pieces(stm); // Don't allow pinned pieces to attack (except the king) as long as - // all pinners are on their original square. - if (!(st->pinners[~stm] & ~occupied)) + // any pinners are on their original square. + if (st->pinners[~stm] & occupied) stmAttackers &= ~st->blockersForKing[stm]; // If stm has no more attackers then give up: stm loses