CS 391 Selected Topics: Game AI Homework #7 |

**Note: **This work is to be done in **groups of 2**. Each group will submit one assignment. Although
you may divide the work, both team members should be able to present/describe
their partner's work upon request.

Implement YahtzeeSolver.java according to these specifications in order to optimize solitaire score. You will be given starter code for YahtzeeSolver via email. The correct output to the test main methods provided is given here.

Outline of computation:

- For each turn from the last to the first:
- For each widget of that turn:
- Compute optimal play and score expectation after the second
reroll:
- For each roll:
- For each unscored scoring category,
- Compute the immediate score for the roll
- Compute the future expected score (either from the widget that would follow, or the value of 35 or 0 at game end depending on whether the bonus was achieved or not)
- Compute total expected future score by adding the immediate score increase and future score expectations.

- Record the scoring category and total expected future score where the latter is maximized.

- For each unscored scoring category,

- For each roll:
- Compute optimal play and score expectation after the first
reroll:
- For each roll:
- Compute the best immediate scoring category just as after the second reroll.
- Additionally, for each possible reroll:
- Compute the probability of the reroll
- Compute the resulting roll
- Look up the corresponding score expectation
- Add the probability times the score expectation to the total expected score for the reroll action

- Record the reroll or immediate scoring action that yields the maximum expected future score.

- For each roll:
- Compute optimal play and score expectation after the first roll just as in the previous step.
- Compute the widget score expectation as the expected future
score of
*any*roll where one rerolls all dice (to simulate the first roll of all dice at the beginning of the turn). This is much like an inner loop of the previous steps. - Store the widget expected future score for use in the computation of preceding widgets.

- Compute optimal play and score expectation after the second
reroll:

- For each widget of that turn:

Note that returning the optimal play and score from the `getOptimalActionAndScore`

method then simply amounts to selecting the current
relevant widget and recomputing optimal play for that widget until the optimal
play has been computed and then simply return it.

Take special care to encode plays as specified.