def quiesce(board, alpha, beta, evaluate):
    """Search for all moves that would lead to a capture of own piece.
    A 'quiet' move is one that ends without a chance of capture.
    
    Standing pat:
    In order to allow the quiescence search to stabilize, we need to be able to
    stop searching without necessarily searching all available captures. In 
    addition, we need a score to return in case there are no captures available
    to be played. This is done by a using the static evaluation as a "stand-pat"
    score (the term is taken from the game of poker, where it denotes playing
    one's hand without drawing more cards). At the beginning of quiescence, the
    position's evaluation is used to establish a lower bound on the score. This
    is theoretically sound because we can usually assume that there is at least
    one move that can either match or beat the lower bound. If the lower bound
    from the stand pat score is already greater than or equal to beta, we can 
    return the stand pat score (fail-soft) or beta (fail-hard) as a lower bound.
    Otherwise, the search continues, keeping the evaluated "stand-pat" score as
    an lower bound if it exceeds alpha, to see if any tactical moves can 
    increase alpha.
    """
    
    # Get lower bound (standing pat) score
    stand_pat = evaluate(board)
    
    # Check if standing pat score is better than beta.
    # If so, assume other player would not follow this route
    if stand_pat >= beta:
        return beta
    
    # Update alpha if standing pat score is better
    if alpha < stand_pat:
        alpha = stand_pat

    # Iterate through legal moves (from the opposing player)
    for move in board.legal_moves:
        # Check if moves leads to capture
        if board.is_capture(move):
            # Keep iterating until a quiet move is found
            board.push(move)        
            score = -quiesce(board, -beta, -alpha, evaluate)
            
            # Restore the previous position.
            board.pop()

            # Cehck if score > beta. If so, oppenent wil not go down this route
            if score >= beta:
                return beta
            
            # Update alpha if score is best explored option on this path
            if score > alpha:
                alpha = score  
    
    # Return alpha, the best score in this path
    return alpha