```python
"""Cut a fabric roll for the greatest takings the price board allows."""


def cut_roll(length: int, board: list[tuple[int, int]]) -> dict:
    if isinstance(length, bool) or not isinstance(length, int) or length < 0:
        raise ValueError("length must be a non-negative whole number")
    
    # Sort board pieces by price in descending order
    order = sorted(board, key=lambda entry: -entry[1])
    
    # Initialize DP table to store the best takings for each roll length
    dp_table = [0] * (length + 1)
    
    # Initialize a list to keep track of the piece cut at each step
    pieces = []
    
    # Fill the DP table
    for length in range(1, length + 1):
        best_value = -1
        best_piece = 0
        
        # Check each board piece to see if it can be used
        for piece, price in order:
            if piece <= length and price + dp_table[length - piece] > best_value:
                best_value = price + dp_table[length - piece]
                best_piece = piece
        
        # Update the DP table with the best value found
        dp_table[length] = best_value
        
        # If a piece was used, add it to the pieces list
        if best_piece > 0:
            pieces.append(best_piece)
    
    # Remove duplicates and sort the pieces in descending order
    pieces = sorted(set(pieces), reverse=True)
    
    # Return the result as a dictionary
    return {"takings": dp_table[-1], "pieces": pieces}
```