The problem I needed to solve
A project’s deck definition should not be the same object as the deck players draw from. I needed a reusable definition and separate state for each match.
Implementation in this snapshot
RuntimeDeck validates DeckDefinition first. Reset creates fresh instances and clears DrawPile and DrawnCards; Draw moves the first card into the drawn collection.
The design decision and its cost
Draw throws explicitly, while TryDraw returns false for an empty deck. These paths let me separate an ordinary game condition from a violated programming contract.
Current boundaries
DrawMany checks availability before drawing, but removing from the front of a List shifts elements. This implementation does not establish that it is optimized for very large decks.
Restarting and tracking drawn cards
Suppose a hand ends and the player chooses to restart. RuntimeDeck.Reset does more than refill the remaining-card list: it clears DrawnCards and obtains fresh instances from DeckDefinition. Cards from the previous match should not contribute to the next match’s counts. Reset does not call Shuffle, however. The new order comes from the deck definition, and the caller still decides whether to shuffle. Restarting and randomizing remain independent operations.
Before its first draw, DrawMany checks that the amount is positive and RemainingCount is sufficient. Asking for ten cards when only nine remain fails before partially consuming the deck. That is easier to reason about than an incomplete deal. This precheck is not a general transaction, though: DrawMany still performs successive Draw calls and does not govern failures in a consumer that later adds the returned cards to a player’s hand.
DrawnCards can be a misleading name: it records cards leaving the deck, rather than their current locations on the table. A drawn card may later be in a hand, the table center or a collected pile; this class does not track those movements. IReadOnlyList provides read access but does not create a separate snapshot. Subsequent draws change the underlying list. A consumer needing a stable report for one moment must make the appropriate copy and preserve that report’s meaning.
What this stage taught me
For Dalo, the useful outcome is restarting from one stable definition. Remaining and drawn cards are observable without turning the deck asset itself into a particular match’s mutable state.




