Editorial illustration: A trick winner is not a match winner

A trick winner is not a match winner

The problem I needed to solve

Four table cards cannot be resolved through a simple numeric comparison. Trump and lead suit determine which cards compete; rank strength matters only afterward.

Implementation in this snapshot

HokmTrickWinnerResolver.ResolveWinner first checks whether trump appears in the trick. Trump is the winning suit if present; otherwise it is the lead suit. GetRankStrength then finds its strongest card.

The design decision and its cost

The result supplies winning seat and team, with rank strength defined by configuration. I did not equate a card’s enum value with its strength in Hokm.

Current boundaries

Resolution requires four played cards and a defined lead suit. Winning a trick is also not winning the match; scoring and assigning the next leader belong to subsequent services.

Choose the competing suit before comparing ranks

Imagine a trick led with a non-trump ace followed by a small trump. Direct rank comparison could incorrectly award the ace the trick. ResolveWinner first checks whether trump appears. If so, only trump cards compete; otherwise the lead suit determines eligibility. This decision order matters more than simple sorting. A high rank in an unrelated suit cannot win merely because its numeric value is large.

Eligible cards get strength from config.GetRankStrength. The resolver replaces bestPlayedCard when it finds a higher strength and skips nonpositive strengths. Its result includes winner seat and team, lead and trump suits, whether trump appeared and winning strength. Consumers can explain the decision without interpreting rendered card text again. An explainable result still depends on valid input and rank configuration.

ResolveWinner is not a side-effect-free query: it calls trickState.SetCurrentWinner after resolving the winner. Coordinators need to account for that mutation when reading or repeating the call. Missing lead suit or an incomplete four-card trick raises an error. The resolver does not award match points or collect the table cards, leaving winner resolution, announcement, collection and next-leader assignment as explicit steps.

What this stage taught me

This boundary prevented a conceptual mistake: the winner must be selected among cards eligible to compete. The result can then support scoring, collection and the next lead.

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