+ 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(-206) * depth))
- continue;
+ if (!pos.see_ge(move, occupied, Value(-206) * depth))
+ {
+ if (depth < 2 - capture)
+ continue;
+ // don't prune move if a heavy enemy piece (KQR) is under attack after the exchanges
+ Bitboard leftEnemies = (pos.pieces(~us, QUEEN, ROOK) | pos.pieces(~us, KING)) & 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;
+ // exclude Queen/Rook(s) which were already threatened before SEE
+ if (attacks && (sq != pos.square<KING>(~us) && (pos.attackers_to(sq, pos.pieces()) & pos.pieces(us))))
+ attacks = 0;
+ }
+ if (!attacks)
+ continue;
+ }
}
else
{
lmrDepth = std::max(lmrDepth, 0);
+ Bitboard occupied;
// Prune moves with negative SEE (~4 Elo)
- if (!pos.see_ge(move, Value(-24 * lmrDepth * lmrDepth - 15 * lmrDepth)))
+ if (!pos.see_ge(move, occupied, Value(-24 * lmrDepth * lmrDepth - 15 * lmrDepth)))
continue;
}
}
prevSq);
int quietCheckEvasions = 0;
+ Bitboard occupied;
// Step 5. Loop through all pseudo-legal moves until no moves remain
// or a beta cutoff occurs.
continue;
}
- if (futilityBase <= alpha && !pos.see_ge(move, VALUE_ZERO + 1))
+ if (futilityBase <= alpha && !pos.see_ge(move, occupied, VALUE_ZERO + 1))
{
bestValue = std::max(bestValue, futilityBase);
continue;
continue;
// Do not search moves with bad enough SEE values (~5 Elo)
- if (!pos.see_ge(move, Value(-110)))
+ if (!pos.see_ge(move, occupied, Value(-110)))
continue;
}