X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fposition.cpp;h=5dc94a634d665b08e878931ac1b7bb38389da8fa;hp=3526a3d023a5ef38a9e214193bb15820cd30f780;hb=55948623e7b8ad1fc6624cd06733b16d295eecb8;hpb=a6c5b4c6fbd1db45377f9dfecd361cebffe27a8d diff --git a/src/position.cpp b/src/position.cpp index 3526a3d0..5dc94a63 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -68,22 +68,19 @@ PieceType min_attacker(const Bitboard* bb, const Square& to, const Bitboard& stm Bitboard& occupied, Bitboard& attackers) { Bitboard b = stmAttackers & bb[Pt]; + if (!b) + return min_attacker(bb, to, stmAttackers, occupied, attackers); - if (b) - { - occupied ^= b & ~(b - 1); - - if (Pt == PAWN || Pt == BISHOP || Pt == QUEEN) - attackers |= attacks_bb(to, occupied) & (bb[BISHOP] | bb[QUEEN]); + occupied ^= b & ~(b - 1); - if (Pt == ROOK || Pt == QUEEN) - attackers |= attacks_bb(to, occupied) & (bb[ROOK] | bb[QUEEN]); + if (Pt == PAWN || Pt == BISHOP || Pt == QUEEN) + attackers |= attacks_bb(to, occupied) & (bb[BISHOP] | bb[QUEEN]); - attackers &= occupied; // Remove the just found attacker + if (Pt == ROOK || Pt == QUEEN) + attackers |= attacks_bb(to, occupied) & (bb[ROOK] | bb[QUEEN]); - return (PieceType)Pt; - } - return min_attacker(bb, to, stmAttackers, occupied, attackers); + attackers &= occupied; // After X-ray that may add already processed pieces + return (PieceType)Pt; } template<> FORCE_INLINE @@ -395,16 +392,18 @@ const string Position::pretty(Move move) const { string brd = twoRows + twoRows + twoRows + twoRows + dottedLine; + for (Bitboard b = pieces(); b; ) + { + Square s = pop_lsb(&b); + brd[513 - 68 * rank_of(s) + 4 * file_of(s)] = PieceToChar[piece_on(s)]; + } + std::ostringstream ss; if (move) ss << "\nMove: " << (sideToMove == BLACK ? ".." : "") << move_to_san(*const_cast(this), move); - for (Square sq = SQ_A1; sq <= SQ_H8; sq++) - if (piece_on(sq) != NO_PIECE) - brd[513 - 68*rank_of(sq) + 4*file_of(sq)] = PieceToChar[piece_on(sq)]; - ss << brd << "\nFen: " << fen() << "\nKey: " << std::hex << std::uppercase << std::setfill('0') << std::setw(16) << st->key << "\nCheckers: "; @@ -545,7 +544,7 @@ bool Position::is_pseudo_legal(const Move m) const { return false; // The destination square cannot be occupied by a friendly piece - if (piece_on(to) != NO_PIECE && color_of(piece_on(to)) == us) + if (pieces(us) & to) return false; // Handle the special case of a pawn move @@ -655,7 +654,7 @@ bool Position::move_gives_check(Move m, const CheckInfo& ci) const { return true; // Discovery check ? - if (ci.dcCandidates && (ci.dcCandidates & from)) + if (unlikely(ci.dcCandidates) && (ci.dcCandidates & from)) { // For pawn and king moves we need to verify also direction if ( (pt != PAWN && pt != KING) @@ -1154,36 +1153,31 @@ int Position::see(Move m, int asymmThreshold) const { from = from_sq(m); to = to_sq(m); - captured = type_of(piece_on(to)); + swapList[0] = PieceValue[MG][type_of(piece_on(to))]; + stm = color_of(piece_on(from)); occupied = pieces() ^ from; - // Handle en passant moves + // Castle moves are implemented as king capturing the rook so cannot be + // handled correctly. Simply return 0 that is always the correct value + // unless in the rare case the rook ends up under attack. + if (type_of(m) == CASTLE) + return 0; + if (type_of(m) == ENPASSANT) { - Square capQq = to - pawn_push(sideToMove); - - assert(!captured); - assert(type_of(piece_on(capQq)) == PAWN); - - // Remove the captured pawn - occupied ^= capQq; - captured = PAWN; + occupied ^= to - pawn_push(stm); // Remove the captured pawn + swapList[0] = PieceValue[MG][PAWN]; } - else if (type_of(m) == CASTLE) - // Castle moves are implemented as king capturing the rook so cannot be - // handled correctly. Simply return 0 that is always the correct value - // unless the rook is ends up under attack. - return 0; // Find all attackers to the destination square, with the moving piece // removed, but possibly an X-ray attacker added behind it. - attackers = attackers_to(to, occupied); + attackers = attackers_to(to, occupied) & occupied; // If the opponent has no attackers we are finished - stm = ~color_of(piece_on(from)); + stm = ~stm; stmAttackers = attackers & pieces(stm); if (!stmAttackers) - return PieceValue[MG][captured]; + return swapList[0]; // The destination square is defended, which makes things rather more // difficult to compute. We proceed by building up a "swap list" containing @@ -1191,18 +1185,11 @@ int Position::see(Move m, int asymmThreshold) const { // destination square, where the sides alternately capture, and always // capture with the least valuable piece. After each capture, we look for // new X-ray attacks from behind the capturing piece. - swapList[0] = PieceValue[MG][captured]; captured = type_of(piece_on(from)); do { assert(slIndex < 32); - if (captured == KING) // Stop before processing a king capture - { - swapList[slIndex++] = QueenValueMg * 16; - break; - } - // Add the new entry to the swap list swapList[slIndex] = -swapList[slIndex - 1] + PieceValue[MG][captured]; slIndex++; @@ -1212,6 +1199,13 @@ int Position::see(Move m, int asymmThreshold) const { stm = ~stm; stmAttackers = attackers & pieces(stm); + // Stop before processing a king capture + if (captured == KING && stmAttackers) + { + swapList[slIndex++] = QueenValueMg * 16; + break; + } + } while (stmAttackers); // If we are doing asymmetric SEE evaluation and the same side does the first