- // 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;
- }
-
-
- // 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 p;
-
- assert(m1 && move_is_ok(m1));
- assert(m2 && move_is_ok(m2));
-
- // Case 1: The moving piece is the same in both moves
- f2 = move_from(m2);
- t1 = move_to(m1);
- if (f2 == t1)
- return true;
-
- // Case 2: The destination square for m2 was vacated by m1
- t2 = move_to(m2);
- f1 = move_from(m1);
- if (t2 == f1)
- return true;
-
- // Case 3: Moving through the vacated square
- if ( piece_is_slider(pos.piece_on(f2))
- && bit_is_set(squares_between(f2, t2), f1))
- return true;
-
- // Case 4: The destination square for m2 is defended by the moving piece in m1
- p = pos.piece_on(t1);
- if (bit_is_set(pos.attacks_from(p, t1), t2))
- return true;
-
- // Case 5: Discovered check, checking piece is the piece moved in m1
- if ( piece_is_slider(p)
- && bit_is_set(squares_between(t1, pos.king_square(pos.side_to_move())), f2)
- && !bit_is_set(squares_between(t1, pos.king_square(pos.side_to_move())), t2))
- {
- // discovered_check_candidates() works also if the Position's side to
- // move is the opposite of the checking piece.
- Color them = opposite_color(pos.side_to_move());
- Bitboard dcCandidates = pos.discovered_check_candidates(them);
-
- if (bit_is_set(dcCandidates, f2))
- return true;
- }
- return false;
- }
-
-