Skip to content

chooseAction

Sent whenever the player has priority and may take a legal action or pass - cast a spell, play a land, activate an ability, or do nothing. Unlike the modal prompts, the reference client doesn’t show a dialog for this: it highlights the available actions directly on the board.

input.type is "chooseAction". The remaining fields:

interface ChooseActionInput {
actions: Array<AvailableAction>;
}

References: AvailableAction

Each cast/play action has one typed mode. Room unlocks use { type: "unlockDoor", door: "left" | "right" }; Suspend uses { type: "alternative", cost: "suspend" }. These operations retain the existing action kinds and dispatch through the advertised action ID.

Optional faceIndex identifies the face that owns a cast or activated ability. It is independent of the mode: a back-face spell can use mode: { type: "normal" }. Activated leveling abilities use optional levelUp: "class" | "creature". There is no separate mechanic field or isClassLevelUp flag.

Action availability and live card state are separate. For example, an unlock action offers a legal choice, while CardDto.unlockedDoors describes which doors are already unlocked.

There’s no dialog - while you hold priority, each entry in actions is highlighted in place.

A board with playable cards and phase steps highlighted

Available actions glow on the board: castable cards in hand, activatable permanents, and the steps on the phase strip. Clicking a highlight sends { type: "act", actionId } for the matching action.

A card with a picker listing two abilities

When one card offers several abilities, selecting it opens a small picker to choose which activateAbility to use - here, Sunken Hollow’s two mana abilities.

type ChooseActionOutput =
| { type: "pass"; until?: PassUntil; exhaustStack: boolean }
| { type: "act"; actionId: string };
type PassUntil = { playerId: string; phase: StepKind; throughCombat: boolean };

Send { type: "act", actionId } to perform an action by its id - including tapping a mana source or untapping one (undoMana), which appear in actions like any other entry. actionId MUST be an id advertised in this prompt’s actions; anything else is rejected. Send pass to pass priority; the optional until asks the engine to keep auto-passing until playerId reaches phase (a StepKind). exhaustStack: true asks the engine to keep auto-passing until every object currently on the stack has resolved; the fast-forward ends early - priority comes back with a fresh prompt - as soon as any new object (a spell, an activated ability, or a trigger) is put on the stack, so the passing player can respond to it. Conceding is not a response - it is the out-of-band directive message (see Answering a prompt), legal at any time.

{
"promptId": 7,
"decidingPlayerId": "player-0",
"input": {
"type": "chooseAction",
"actions": [
{
"id": "act-0",
"type": "cast",
"cardId": "hand-2",
"mode": { "type": "normal" },
"label": "Cast Lightning Bolt"
},
{
"id": "tap:perm-5:0",
"type": "activateAbility",
"cardId": "perm-5",
"abilityIndex": 0,
"description": "{T}: Add {G}.",
"isManaAbility": true,
"producedMana": [{ "color": "G", "amount": 1 }]
}
]
}
}
{
"kind": "response",
"promptId": 7,
"action": {
"type": "chooseAction",
"output": {
"type": "pass",
"exhaustStack": false
}
}
}