+ // 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)
+ {
+ Bitboard b, occ, oldAtt, newAtt, kingAtt;
+ Square from, to, ksq, victimSq;
+ Piece pc;
+ Color them;
+ Value futilityValue, bv = *bestValue;
+
+ from = move_from(move);
+ 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)
+ {
+ victimSq = pop_1st_bit(&b);
+ futilityValue = futilityBase + pos.endgame_value_of_piece_on(victimSq);
+
+ // Note that here we generate illegal "double move"!
+ if ( futilityValue >= beta
+ && pos.see_sign(make_move(from, victimSq)) >= 0)
+ return true;
+
+ if (futilityValue > bv)
+ bv = futilityValue;
+ }
+
+ // Update bestValue only if check is not dangerous (because we will prune the move)
+ *bestValue = bv;
+ return false;
+ }
+
+