Skip to content

Commit

Permalink
Reintroduce SEE verification against discovered attacks
Browse files Browse the repository at this point in the history
Reintroduces #4453
along with #4469

Leaving out
#4533
#4572

Passed STC:
https://tests.stockfishchess.org/tests/view/647d8c37726f6b400e408a0a
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 143168 W: 38346 L: 37892 D: 66930
Ptnml(0-2): 352, 15672, 39164, 15962, 434

Passed LTC:
https://tests.stockfishchess.org/tests/view/647ee8c528c4431bcb58e432
LLR: 2.94 (-2.94,2.94) <0.50,2.50>
Total: 71538 W: 19560 L: 19190 D: 32788
Ptnml(0-2): 49, 6905, 21499, 7259, 57

closes #4609

bench: 2595430
  • Loading branch information
pb00068 authored and snicolet committed Jun 11, 2023
1 parent a9a6915 commit e1dd005
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 9 deletions.
19 changes: 12 additions & 7 deletions src/position.cpp
Expand Up @@ -1061,7 +1061,7 @@ Key Position::key_after(Move m) const {
/// SEE value of move is greater or equal to the given threshold. We'll use an
/// algorithm similar to alpha-beta pruning with a null window.

bool Position::see_ge(Move m, Value threshold) const {
bool Position::see_ge(Move m, Bitboard& occupied, Value threshold) const {

assert(is_ok(m));

Expand All @@ -1080,7 +1080,7 @@ bool Position::see_ge(Move m, Value threshold) const {
return true;

assert(color_of(piece_on(from)) == sideToMove);
Bitboard occupied = pieces() ^ from ^ to; // xoring to is important for pinned piece logic
occupied = pieces() ^ from ^ to; // xoring to is important for pinned piece logic
Color stm = sideToMove;
Bitboard attackers = attackers_to(to, occupied);
Bitboard stmAttackers, bb;
Expand Down Expand Up @@ -1111,43 +1111,43 @@ bool Position::see_ge(Move m, Value threshold) const {
// the bitboard 'attackers' any X-ray attackers behind it.
if ((bb = stmAttackers & pieces(PAWN)))
{
occupied ^= least_significant_square_bb(bb);
if ((swap = PawnValueMg - swap) < res)
break;
occupied ^= least_significant_square_bb(bb);

attackers |= attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN);
}

else if ((bb = stmAttackers & pieces(KNIGHT)))
{
occupied ^= least_significant_square_bb(bb);
if ((swap = KnightValueMg - swap) < res)
break;
occupied ^= least_significant_square_bb(bb);
}

else if ((bb = stmAttackers & pieces(BISHOP)))
{
occupied ^= least_significant_square_bb(bb);
if ((swap = BishopValueMg - swap) < res)
break;
occupied ^= least_significant_square_bb(bb);

attackers |= attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN);
}

else if ((bb = stmAttackers & pieces(ROOK)))
{
occupied ^= least_significant_square_bb(bb);
if ((swap = RookValueMg - swap) < res)
break;
occupied ^= least_significant_square_bb(bb);

attackers |= attacks_bb<ROOK>(to, occupied) & pieces(ROOK, QUEEN);
}

else if ((bb = stmAttackers & pieces(QUEEN)))
{
occupied ^= least_significant_square_bb(bb);
if ((swap = QueenValueMg - swap) < res)
break;
occupied ^= least_significant_square_bb(bb);

attackers |= (attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN))
| (attacks_bb<ROOK >(to, occupied) & pieces(ROOK , QUEEN));
Expand All @@ -1162,6 +1162,11 @@ bool Position::see_ge(Move m, Value threshold) const {
return bool(res);
}

bool Position::see_ge(Move m, Value threshold) const {
Bitboard occupied;
return see_ge(m, occupied, threshold);
}


/// Position::is_draw() tests whether the position is drawn by 50-move rule
/// or by repetition. It does not detect stalemates.
Expand Down
1 change: 1 addition & 0 deletions src/position.h
Expand Up @@ -144,6 +144,7 @@ class Position {

// Static Exchange Evaluation
bool see_ge(Move m, Value threshold = VALUE_ZERO) const;
bool see_ge(Move m, Bitboard& occupied, Value threshold = VALUE_ZERO) const;

// Accessing hash keys
Key key() const;
Expand Down
23 changes: 21 additions & 2 deletions src/search.cpp
Expand Up @@ -990,9 +990,28 @@ namespace {
+ captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] / 7 < alpha)
continue;

Bitboard occupied;
// SEE based pruning (~11 Elo)
if (!pos.see_ge(move, Value(-205) * depth))
continue;
if (!pos.see_ge(move, occupied, Value(-205) * depth))
{
if (depth < 2 - capture)
continue;
// Don't prune the move if opponent Queen/Rook is under discovered attack after the exchanges
// Don't prune the move if opponent King is under discovered attack after or during the exchanges
Bitboard leftEnemies = (pos.pieces(~us, KING, QUEEN, ROOK)) & occupied;
Bitboard attacks = 0;
occupied |= to_sq(move);
while (leftEnemies && !attacks)
{
Square sq = pop_lsb(leftEnemies);
attacks |= pos.attackers_to(sq, occupied) & pos.pieces(us) & occupied;
// don't consider pieces which were already threatened/hanging before SEE exchanges
if (attacks && (sq != pos.square<KING>(~us) && (pos.attackers_to(sq, pos.pieces()) & pos.pieces(us))))
attacks = 0;
}
if (!attacks)
continue;
}
}
else
{
Expand Down

0 comments on commit e1dd005

Please sign in to comment.