Editorial illustration: Drawing a Joker card as a transaction

Drawing a Joker card as a transaction

The problem I needed to solve

A Joker draw has several stages: transfer, a possible pair, shuffle and turn progression. Accepting unrelated requests at each stage could separate model and presentation.

Implementation in this snapshot

JokerGame.TryDraw performs the logical transfer and creates one pendingMove. New moves are rejected until CompleteMove finishes that exact move; matched cards must actually have left the receiver’s hand.

The design decision and its cost

The runner detaches and transfers the same view, presents a pair and shuffles only the receiver. The sequence follows the accepted result rather than animation guesses.

Current boundaries

pendingMove is not a server transaction or automatic rollback. Stopping and restarting need coroutine, tween and orphan-view cleanup; the runner’s version token matters for obsolete sequences.

Review scenarios and contract meaning

An accepted move is more than an immediate card transfer. It may create a pair in the receiving hand, remove that pair, change the hand order and then advance the turn. pendingMove keeps these stages attached to one action. A second touch during presentation should not let the model accept another action against a partially presented state. CompleteMove also requires the paired cards to have actually left the receiver’s hand: showing removal without changing the model is insufficient to finish. This boundary keeps the logical result and table presentation connected.

Transferring the same detached view preserves card identity through presentation. The runner’s version token matters when an older sequence is still awaiting continuation after a stop or restart; that sequence must not alter the new game. This is still not automatic rollback or a database transaction. Cancellation must clean up tweens, coroutines and unowned views. Relevant scenarios include stopping during transfer, stopping during pair removal and restarting. A move lock does not establish every cancellation path is correct; those paths are an independent part of flow quality.

Reporting should also distinguish move acceptance from presentation completion. A touch requests an action, TryDraw establishes model acceptance, and animation completion is another signal. Combining them can misinterpret interrupted presentation as rule rejection. pendingMove motivates this diagnostic principle without proving the project contains dedicated reporting for every stage.

What this stage taught me

For me, a transaction here means one accepted action with a clear beginning and end. Animation gets time to run without a second tap executing gameplay midway through its presentation.

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