1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-04-29 16:23:09 +00:00

Second cleanup wave on check_is_useless()

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
Marco Costalba 2010-12-15 09:14:01 +01:00
parent 47f5560e2d
commit 201e8d5f87
3 changed files with 72 additions and 90 deletions

View file

@ -521,16 +521,24 @@ Bitboard Position::attacks_from(Piece p, Square s) const {
switch (p) switch (p)
{ {
case WP: return attacks_from<PAWN>(s, WHITE);
case BP: return attacks_from<PAWN>(s, BLACK);
case WN: case BN: return attacks_from<KNIGHT>(s);
case WB: case BB: return attacks_from<BISHOP>(s); case WB: case BB: return attacks_from<BISHOP>(s);
case WR: case BR: return attacks_from<ROOK>(s); case WR: case BR: return attacks_from<ROOK>(s);
case WQ: case BQ: return attacks_from<QUEEN>(s); case WQ: case BQ: return attacks_from<QUEEN>(s);
case WK: case BK: return attacks_from<KING>(s); default: return StepAttackBB[p][s];
default: break; }
}
Bitboard Position::attacks_from(Piece p, Square s, Bitboard occ) {
assert(square_is_ok(s));
switch (p)
{
case WB: case BB: return bishop_attacks_bb(s, occ);
case WR: case BR: return rook_attacks_bb(s, occ);
case WQ: case BQ: return bishop_attacks_bb(s, occ) | rook_attacks_bb(s, occ);
default: return StepAttackBB[p][s];
} }
return false;
} }

View file

@ -197,6 +197,7 @@ public:
// Information about attacks to or from a given square // Information about attacks to or from a given square
Bitboard attackers_to(Square s) const; Bitboard attackers_to(Square s) const;
Bitboard attacks_from(Piece p, Square s) const; Bitboard attacks_from(Piece p, Square s) const;
static Bitboard attacks_from(Piece p, Square s, Bitboard occ);
template<PieceType> Bitboard attacks_from(Square s) const; template<PieceType> Bitboard attacks_from(Square s) const;
template<PieceType> Bitboard attacks_from(Square s, Color c) const; template<PieceType> Bitboard attacks_from(Square s, Color c) const;

View file

@ -297,8 +297,7 @@ namespace {
template <NodeType PvNode> template <NodeType PvNode>
Depth extension(const Position& pos, Move m, bool captureOrPromotion, bool moveIsCheck, bool singleEvasion, bool mateThreat, bool* dangerous); Depth extension(const Position& pos, Move m, bool captureOrPromotion, bool moveIsCheck, bool singleEvasion, bool mateThreat, bool* dangerous);
bool check_is_useless(Position &pos, Move move, Value eval, Value futilityBase, Value beta, Value *bValue); bool check_is_dangerous(Position &pos, Move move, Value futilityBase, Value beta, Value *bValue);
Bitboard attacks(const Piece P, const Square sq, const Bitboard occ);
bool connected_moves(const Position& pos, Move m1, Move m2); bool connected_moves(const Position& pos, Move m1, Move m2);
bool value_is_mate(Value value); bool value_is_mate(Value value);
Value value_to_tt(Value v, int ply); Value value_to_tt(Value v, int ply);
@ -1588,12 +1587,17 @@ split_point_start: // At split points actual search starts from here
// Don't search useless checks // Don't search useless checks
if ( !PvNode if ( !PvNode
&& !isCheck && !isCheck
&& moveIsCheck && moveIsCheck
&& move != ttMove && move != ttMove
&& !pos.move_is_capture(move) && !pos.move_is_capture_or_promotion(move)
&& !move_is_promotion(move) && ss->eval + PawnValueMidgame / 4 < beta
&& check_is_useless(pos, move, ss->eval, futilityBase, beta, &bestValue)) && !check_is_dangerous(pos, move, futilityBase, beta, &bestValue))
{
if (ss->eval + PawnValueMidgame / 4 > bestValue)
bestValue = ss->eval + PawnValueMidgame / 4;
continue; continue;
}
// Update current move // Update current move
ss->currentMove = move; ss->currentMove = move;
@ -1631,94 +1635,63 @@ split_point_start: // At split points actual search starts from here
return bestValue; return bestValue;
} }
// check_is_useless() tests if a checking move can be pruned in qsearch().
// bestValue is updated when necesary.
bool check_is_useless(Position &pos, Move move, Value eval, Value futilityBase, Value beta, Value *bValue) // check_is_dangerous() tests if a checking move can be pruned in qsearch().
// bestValue is updated only when returning false because in that case move
// will be pruned.
bool check_is_dangerous(Position &pos, Move move, Value futilityBase, Value beta, Value *bestValue)
{ {
Value bestValue = *bValue; Bitboard b, occ, oldAtt, newAtt, kingAtt;
Square from, to, ksq, victimSq;
Piece pc;
Color them;
Value futilityValue, bv = *bestValue;
/// Rule 1. Using checks to reposition pieces when close to beta from = move_from(move);
if (eval + PawnValueMidgame / 4 < beta) to = move_to(move);
them = opposite_color(pos.side_to_move());
ksq = pos.king_square(them);
kingAtt = pos.attacks_from<KING>(ksq);
pc = pos.piece_on(from);
occ = pos.occupied_squares() & ~(1ULL << from) & ~(1ULL << ksq);
oldAtt = pos.attacks_from(pc, from, occ);
newAtt = pos.attacks_from(pc, to, occ);
// Rule 1. Checks which give opponent's king at most one escape square are dangerous
b = kingAtt & ~pos.pieces_of_color(them) & ~newAtt & ~(1ULL << to);
if (!(b && (b & (b - 1))))
return true;
// Rule 2. Queen contact check is very dangerous
if ( type_of_piece(pc) == QUEEN
&& bit_is_set(kingAtt, to))
return true;
// Rule 3. Creating new double threats with checks
b = pos.pieces_of_color(them) & newAtt & ~oldAtt & ~(1ULL << ksq);
while (b)
{ {
if (eval + PawnValueMidgame / 4 > bestValue) victimSq = pop_1st_bit(&b);
bestValue = eval + PawnValueMidgame / 4; futilityValue = futilityBase + pos.endgame_value_of_piece_on(victimSq);
}
else
return false;
Square from = move_from(move);
Square to = move_to(move);
Color oppColor = opposite_color(pos.side_to_move());
Square oppKing = pos.king_square(oppColor);
Bitboard occ = pos.occupied_squares() & ~(1ULL << from) & ~(1ULL <<oppKing);
Bitboard oppOcc = pos.pieces_of_color(oppColor) & ~(1ULL <<oppKing);
Bitboard oldAtt = attacks(pos.piece_on(from), from, occ);
Bitboard newAtt = attacks(pos.piece_on(from), to, occ);
// Rule 2. Checks which give opponent's king at most one escape square are dangerous
Bitboard escapeBB = attacks(WK, oppKing, 0) & ~oppOcc & ~newAtt & ~(1ULL << to);
if (!escapeBB)
return false;
if (!(escapeBB & (escapeBB - 1)))
return false;
/// Rule 3. Queen contact check is very dangerous
if ( pos.type_of_piece_on(from) == QUEEN
&& bit_is_set(attacks(WK, oppKing, 0), to))
return false;
/// Rule 4. Creating new double threats with checks
Bitboard newVictims = oppOcc & ~oldAtt & newAtt;
while(newVictims)
{
Square victimSq = pop_1st_bit(&newVictims);
Value futilityValue = futilityBase + pos.endgame_value_of_piece_on(victimSq);
// Note that here we generate illegal "double move"! // Note that here we generate illegal "double move"!
if (futilityValue >= beta && pos.see_sign(make_move(from, victimSq)) >= 0) if ( futilityValue >= beta
return false; && pos.see_sign(make_move(from, victimSq)) >= 0)
return true;
if (futilityValue > bestValue) if (futilityValue > bv)
bestValue = futilityValue; bv = futilityValue;
} }
*bValue = bestValue; // Update bestValue only if check is not dangerous (because we will prune the move)
return true; *bestValue = bv;
return false;
} }
// attacks() returns attacked squares.
Bitboard attacks(const Piece P, const Square sq, const Bitboard occ)
{
switch(P)
{
case WP:
case BP:
case WN:
case BN:
case WK:
case BK:
return StepAttackBB[P][sq];
case WB:
case BB:
return bishop_attacks_bb(sq, occ);
case WR:
case BR:
return rook_attacks_bb(sq, occ);
case WQ:
case BQ:
return bishop_attacks_bb(sq, occ) | rook_attacks_bb(sq, occ);
default:
assert(false);
return 0ULL;
}
}
// connected_moves() tests whether two moves are 'connected' in the sense // connected_moves() tests whether two moves are 'connected' in the sense
// that the first move somehow made the second move possible (for instance // that the first move somehow made the second move possible (for instance