- // 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)
- {
- Bitboard b, occ, oldAtt, newAtt, kingAtt;
- Square from, to, ksq;
- Piece pc;
- Color them;
-
- from = from_sq(move);
- to = to_sq(move);
- them = ~pos.side_to_move();
- ksq = pos.king_square(them);
- kingAtt = pos.attacks_from<KING>(ksq);
- pc = pos.piece_moved(move);
-
- occ = pos.pieces() ^ from ^ 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(them) & ~newAtt & ~(1ULL << to);
-
- if (!more_than_one(b))
- return true;
-
- // Rule 2. Queen contact check is very dangerous
- if (type_of(pc) == QUEEN && (kingAtt & to))
- return true;
-
- // Rule 3. Creating new double threats with checks
- b = pos.pieces(them) & newAtt & ~oldAtt & ~(1ULL << ksq);
- while (b)
- {
- // Note that here we generate illegal "double move"!
- if (futilityBase + PieceValue[Eg][pos.piece_on(pop_lsb(&b))] >= beta)
- return true;
- }
-
- return false;
- }
-
-
- // connected_moves() tests whether two moves are 'connected' in the sense
- // that the first move somehow made the second move possible (for instance
- // if the moving piece is the same in both moves). The first move is assumed
- // to be the move that was made to reach the current position, while the
- // second move is assumed to be a move from the current position.
-
- bool connected_moves(const Position& pos, Move m1, Move m2) {
-
- Square f1, t1, f2, t2;
- Piece p1, p2;
- Square ksq;
-
- assert(is_ok(m1));
- assert(is_ok(m2));
-
- // Case 1: The moving piece is the same in both moves
- f2 = from_sq(m2);
- t1 = to_sq(m1);
- if (f2 == t1)
- return true;
-
- // Case 2: The destination square for m2 was vacated by m1
- t2 = to_sq(m2);
- f1 = from_sq(m1);
- if (t2 == f1)
- return true;
-
- // Case 3: Moving through the vacated square
- p2 = pos.piece_on(f2);
- if (piece_is_slider(p2) && (between_bb(f2, t2) & f1))
- return true;
-
- // Case 4: The destination square for m2 is defended by the moving piece in m1
- p1 = pos.piece_on(t1);
- if (pos.attacks_from(p1, t1) & t2)
- return true;
-
- // Case 5: Discovered check, checking piece is the piece moved in m1
- ksq = pos.king_square(pos.side_to_move());
- if ( piece_is_slider(p1)
- && (between_bb(t1, ksq) & f2)
- && (pos.attacks_from(p1, t1, pos.pieces() ^ f2) & ksq))
- return true;
-
- return false;
- }
-
-