Boxes and dice game You have $9$ boxes numbered $1$ through $9$ and then you have two $6$-sided dice.
Each turn you roll the two dice and deduct the sum of the dice from the boxes by removing the number itself or any combination of boxes that sum up to the sum of the dice.
For example, let's say you first roll a $4$ and $5$.
You then have the option to remove some combination of boxes that sum up to $9$ (yes, you can remove $9$ itself too).
After these boxes are removed you roll both dice again and continue until you roll a sum that's impossible to remove with the remaining boxes.
For example, if you're left with boxes $1$, $3$, $4$ and you roll a $10$.
The game is over and your final score is $\sum_{i = 1}^9 i = 45$ minus the sum of the remaining boxes.
So if you were left with $1$, $3$, $4$ you end up with $37$.
Question. What is the optimal strategy?
 A: What you are asking for is a tall order; an optimal strategy is specified by saying, for every possible set of remaining boxes, and every possible roll, which boxes should you remove in that situation. This is simple enough to compute with the help of a computer, using dynamic programming/memoization.
I found that with optimal play, your expected score is $33.842$. Here is a text document summarizing the optimal strategy; it is 1766 lines long. Here is how you interpret the file. The entry
(0, 0, 1, 1, 1, 1, 0, 1, 1)  |  11  |  (6, 5)  

means that when the set of remaining boxes is $\{3, 4, 5, 6, 8, 9\}$, and you roll $11$, then the optimal strategy is to remove boxes numbered $6$ and $5$.
Here is my Python code which I used to create the linked text file containing the optimal strategy.
from functools import lru_cache
from itertools import product

best_moves_dict = dict()

def main():
    
    box_mask = (1,)*9
    
    print(box_game_expected_score(box_mask))
    
    print(len(best_moves_dict))
    
    with open('box_game_strategy.txt', 'w') as f:
        for mask in product([0,1], repeat = 9):
            for roll in range(2, 12 + 1):
                if (mask, roll) in best_moves_dict:
                    f.write(str(mask) + '  |  ')
                    f.write(f'{roll:2}' + '  |  ')
                    f.write(str(best_moves_dict[(mask, roll)]) + '\n')

def distinct_partitions(total, max = None):
    # Yields all tuples of distinct positive integers summing to total.
    # If "max" option is enabled, only yield such tuples whose max entry
    # is at most max.
    
    if total < 0:
        return
    
    if total == 0:
        yield ()
        return
    
    if max == None:
        max = total
    
    if total > max * (max + 1) //2 :
        return
    
    for x in range(max, 0, -1):
        for lamb in distinct_partitions(total - x, x - 1):
            yield (x,) + lamb



@lru_cache
def box_game_expected_score(box_mask):
    
    global best_moves_dict
    
    ans = 0
    
    for roll in range(2, 12 + 1):
        
        roll_prob = (roll - 1) /36 - 2 * max(roll - 7, 0)/36
        
        #Default option is game ends, score sum of removed boxes
        score_if_no_opts = sum([i+1 for i in range(9) if box_mask[i] == 0])
        options = [(score_if_no_opts, None)]
        for indices_to_take in distinct_partitions(roll, max = 9):
            
            if all([box_mask[i-1] for i in indices_to_take]):
                
                new_mask = list(box_mask)
                for i in indices_to_take:
                    new_mask[i-1] = 0
                new_mask = tuple(new_mask)
                
                new_score = box_game_expected_score(new_mask)
                
                options.append((new_score, indices_to_take))
                        
        ans += roll_prob * max(options)[0]
        
        if len(options) >= 3:
            best_moves_dict[(box_mask, roll)] = max(options)[1]
    
    return ans 


main()

