Editorial illustration: Dealing without hardcoded counts

Dealing without hardcoded counts

The problem I needed to solve

I wanted the same core to support both a fixed deal and distributing an entire deck. Hokm’s player and card counts should not leak into every other game.

Implementation in this snapshot

CardDealer.Deal selects a path using DealMode. A fixed deal supports round-robin single-card dealing or dealing each whole hand; the other mode rotates through players until the deck is empty.

The design decision and its cost

DealConfig also controls sorting afterward. DealResult reports player count, cards dealt and remaining cards, keeping logical counts separate from their presentation.

Current boundaries

Fixed dealing checks for insufficient cards before drawing. The service does not invent Hokm’s staged deal or Joker’s no-pair opening; those belong to the game layer.

Equal counts, different dealing orders

Suppose three players each need two cards. DealFixedRoundRobin gives the first three cards to the three players, then makes another pass for their second cards. DealFixedPerPlayer gives two consecutive cards to the first player before proceeding to the second. Final counts are equal, but identical deck order does not produce identical hands. DealOneCardAtATime therefore affects logical allocation rather than appearance alone, and its setting must agree with the game’s rule.

DealUntilDeckEmpty advances a player counter modulo the player count after every draw. If the deck size is not divisible by that count, some players receive an extra card because dealing begins with the first list entry. CardDealer has no parameter for starting halfway through that list. A game can prepare the intended ordering, but must distinguish seat order from method input order. The loop alone does not establish automatic fairness or symmetry.

Validate rejects a missing deck, an empty player list, null players and invalid CardsPerPlayer before dealing. A subtle detail is that CardsPerPlayer must be positive even when emptying the deck, although that mode’s loop does not use it. DealConfig must satisfy the whole current contract. Afterward, SortHandsAfterDeal sorts every hand and DealResult reports counts. Those counts help inspect allocation, but do not govern card-flight timing, sound or trump selection.

What this stage taught me

For me, reuse meant removing unjustified constants. The dealer performs one bounded task, while each game determines when and in what order to call it.

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