# Reference patch — 02-a-third-player-joins

The answer key for how the reference absorbs this change, and the thing that makes
`budget.json` reproducible. **Never shipped to the candidate.**

1. **Overlay** `../contract-delta/Mark.java` and `../contract-delta/Entry.java` onto
   `contract/`. Contract files are given, so nothing here is charged.
2. **Replace** `reference/src/TicTacToeFactory.java` with the file in this directory. `edits.json`
   beside this file is the same edit in machine-readable form.

There is **no new file** and **no change anywhere else**: `TicTacToe`, `Grid`, `StandardGrid`,
`WinRule` and `TurnOrder` are untouched. `TurnOrder` already took a `List<Mark>` and cycled
through however many entries it was given — it never knew there were only ever two players, it
was just never handed more than two. The whole change is: teach the factory a wider entry point,
and have the narrower one call it.

## Measurement

`reference_diff = 6` (5 added, 1 removed, one file touched: `TicTacToeFactory.java`), so
`diff_budget = max(3, 6 + ceil(6/2)) = 9`.

Both suites are green after the patch: the curveball suite **5 tests, 5 passed**, and the base
suite **17 tests, 17 passed** — purely additive, so the standard two-player game keeps working
and does.

## Where the requirement landed, and where it did not

- **`TurnOrder` was not opened.** It already refused fewer than two players and already refused
  a repeated mark, in its own constructor — both because those checks belong with the invariant
  they protect, not because this curveball was anticipated. `Entry.create(3, 3, List.of(Mark.X))`
  and the same list with a mark repeated both fail for free, in the class that was already
  responsible for the rule.
- **`WinRule` and `Grid` were not opened**, because a line of marks is a line of marks whichever
  of three values fills it — `completesLineAt` compares by `==` against whatever mark was handed
  in, and never enumerated the possibilities.
- **The one thing that had to move:** the hardcoded `List.of(Mark.X, Mark.O)` was living at the
  call site (`of(int, int)`), which is exactly where a design that had instead put it inside
  `TurnOrder`'s own default constructor would have made this curveball impossible to reach
  without opening `TurnOrder` itself. Keeping the two-player list a decision the *factory* makes,
  not a default the collaborator assumes, is what the six lines pay for.
