X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fposition.cpp;h=5dc94a634d665b08e878931ac1b7bb38389da8fa;hp=0c81763155d078275263430b17b4a044269daeab;hb=55948623e7b8ad1fc6624cd06733b16d295eecb8;hpb=0504a6975d8f32ee9638e05b53ed32e3f7a7f4e1 diff --git a/src/position.cpp b/src/position.cpp index 0c817631..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) @@ -1136,7 +1135,7 @@ int Position::see_sign(Move m) const { // Early return if SEE cannot be negative because captured piece value // is not less then capturing one. Note that king moves always return // here because king midgame value is set to 0. - if (PieceValue[MG][piece_on(to_sq(m))] >= PieceValue[MG][piece_moved(m)]) + if (PieceValue[MG][piece_moved(m)] <= PieceValue[MG][piece_on(to_sq(m))]) return 1; return see(m); @@ -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,7 +1185,6 @@ 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 { @@ -1206,12 +1199,10 @@ int Position::see(Move m, int asymmThreshold) const { stm = ~stm; stmAttackers = attackers & pieces(stm); - if (captured == KING) + // Stop before processing a king capture + if (captured == KING && stmAttackers) { - // Stop before processing a king capture - if (stmAttackers) - swapList[slIndex++] = QueenValueMg * 16; - + swapList[slIndex++] = QueenValueMg * 16; break; }