Editorial illustration: Following suit and rejecting illegal cards

Following suit and rejecting illegal cards

The problem I needed to solve

Dimming an illegal card is not enough. If a controller or bot submits a move directly, the rules still need to enforce following suit and return a clear result.

Implementation in this snapshot

HokmLegalCardValidator.GetLegalCards permits all cards when no lead suit exists, but restricts the hand to that suit when available. ValidateCardPlay also checks ownership, duplicate seat play and trick completion.

The design decision and its cost

The result includes legal cards alongside validation status. That decision can drive both interface highlighting and bot selection, avoiding two independent versions of the rule.

Current boundaries

This validator receives hand and trick state; it is not the turn manager. Turn ownership still needs checking in the play path, and a correct interface does not replace that check.

A legal-card list is not complete execution authority

If Hearts is the lead suit and the player holds Hearts, GetLegalCards returns only those cards. Without Hearts, it returns all non-null hand entries. This supports explaining the follow-suit restriction in the UI. However, the list builder alone does not reject a completed trick or a seat that already played; ValidateCardPlay handles those checks. A highlighting list must not become permanent authority to execute a move without consulting current state again.

Validation checks missing cards, unsuitable attributes, a completed trick, repeated seat play and absence from the hand before acceptance. HandContainsCard matches through ReferenceEquals or InstanceId, rather than equating cards merely by suit and rank. Rejected results can still carry legalCards, giving consumers both the reason and available options. Translating and presenting that reason remains outside this validator.

AddAllCards filters only null, while standard-card validation happens separately in ValidateCardPlay. Corrupt hand data can therefore yield a list whose members do not pass every later check. The validator also does not know which RuntimePlayer currently owns the turn. Dalo needs both boundaries: follow-suit and ownership here, turn authority in the execution path. A highlighted card cannot replace complete logical validation.

What this stage taught me

For me, illegal-card feedback should come from the same truth gameplay uses. Players should not see a card as playable only to have a different rule reject it at execution.

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