Editorial illustration: Player hands and the sorting problem

Player hands and the sorting problem

The problem I needed to solve

Sorting a hand helps readability in one card game, but can leak information in another. I did not want every added card to automatically change the hand’s order.

Implementation in this snapshot

CardHand separates adding, removing, clearing and Sort. RemoveCardByInstanceId looks up an ID and returns the exact instance it removed.

The design decision and its cost

ICardSortStrategy is replaceable, and the default strategy runs only when Sort is called. I gave that decision to the game flow rather than the card collection.

Current boundaries

AddCard does not reject a duplicate instance, and AddCards can stop midway if it encounters invalid input. This collection alone does not enforce every game invariant.

Ownership apart from hand position

A sensitive situation is selecting a card immediately after receiving several new ones. CardHand.AddCard only rejects null and appends the instance; it does not sort automatically. This preserves arrival order until the game decides sorting is appropriate. Reading suits may matter in Hokm, whereas hand order can influence choosing a card from another player in Joker. A generic collection should not make that presentation decision in advance for both games.

RemoveCardByInstanceId returns both success status and the exact removed object through removedCard. A caller transferring ownership does not need to infer the moved card from suit and rank. RemoveCard instead searches for the supplied instance, and Contains follows the collection’s corresponding contract. None of these methods checks whether a card appears in two hands across the entire game. That wider invariant belongs to the card-transfer flow.

AddCards calls AddCard incrementally. If the third item is null, the first two have already been added, so the operation is not all-or-nothing. Error handling must not assume the hand remained unchanged. Meanwhile, Cards exposes IReadOnlyList and encourages consumers to use explicit collection operations. This makes mutation easier to follow, but does not substitute for validating incoming batches or detecting repeated InstanceIds; those checks are absent from this class.

What this stage taught me

My lesson was that presentation order is a real design choice. Joker hands can shuffle and Hokm hands can sort without rewriting card ownership for each game.

Explore Dalo

Latest devlogs

Editorial illustration: Pasur launch and telemetry in the shared structure

Pasur launch and telemetry in the shared structure

Adding Pasur needs both a correct mode handoff and valid public telemetry.

Read article
Editorial illustration: Presenting selection and captures in Pasur

Presenting selection and captures in Pasur

Pasur motion should explain which hand card was played and which table cards were captured.

Read article
Editorial illustration: Pasur bot decisions from capture options

Pasur bot decisions from capture options

My teammate’s Pasur bot chooses among legal options without inspecting hidden opposing cards.

Read article
Dalo