Пример #1
0
        // refutes() tests whether a 'first' move is able to defend against a 'second'
        // opponent's move. In this case will not be pruned. Normally the second move
        // is the threat (the best move returned from a null search that fails low).
        private static bool refutes(Position pos, int move, int threat)
        {
            Debug.Assert(Utils.is_ok_M(move));
            Debug.Assert(Utils.is_ok_M(threat));
            
            Square mfrom = Utils.from_sq(move);
            Square mto = Utils.to_sq(move);
            Square tfrom = Utils.from_sq(threat);
            Square tto = Utils.to_sq(threat);

            // Don't prune moves of the threatened piece
            if (mfrom == tto)
            {
                return true;
            }

            // If the threatened piece has value less than or equal to the value of the
            // threat piece, don't prune moves which defend it.
            if (pos.is_capture(threat)
                && (Position.PieceValue[PhaseC.MG][pos.piece_on(tfrom)] >= Position.PieceValue[PhaseC.MG][pos.piece_on(tto)]
                    || Utils.type_of(pos.piece_on(tfrom)) == PieceTypeC.KING))
            {
                // Update occupancy as if the piece and the threat are moving
                var occ = Utils.xor_bit(Utils.xor_bit(Utils.xor_bit(pos.occupied_squares, mfrom), mto), tfrom);
                Piece piece = pos.piece_on(mfrom);

                // The piece moved in 'to' attacks the square 's' ?
                if (Utils.bit_is_set(Position.attacks_from(piece, mto, occ), tto) != 0)
                {
                    return true;
                }

                // Scan for possible X-ray attackers behind the moved piece
                var xray = (Utils.rook_attacks_bb(tto, occ)
                        & pos.pieces(PieceTypeC.ROOK, PieceTypeC.QUEEN, Utils.color_of(piece)))
                        | (Utils.bishop_attacks_bb(tto, occ)
                            & pos.pieces(PieceTypeC.BISHOP, PieceTypeC.QUEEN, Utils.color_of(piece)));

                // Verify attackers are triggered by our move and not already existing
                if ((xray != 0) && ((xray ^ (xray & pos.attacks_from_QUEEN(tto))) != 0))
                {
                    return true;
                }
            }

            // Don't prune safe moves which block the threat path
            if ((Utils.bit_is_set(Utils.between_bb(tfrom, tto), mto) != 0) && pos.see(move, true) >= 0)
            {
                return true;
            }

            return false;
        }