Spaces:
Sleeping
Sleeping
LovecaSim: Interaction Cheat Sheet
This document details the interaction flow between the Rust Engine and the Frontend, specifically how abilities pause (suspend) for user input.
Opcode Categorization
1. Automatic (Non-Interactive)
These opcodes resolve immediately without stopping the interpreter.
O_DRAW: Draws cards to hand.O_BOOST: Adds to score bonus.O_BUFF/O_BLADES: Adds power/blades to members.O_ACTIVATE_ENERGY: Untaps energy cards.O_NEGATE: Marks triggers as negated.O_CHARGE: Untaps energy from deck.
2. Mandatory Choices (Suspends)
These opcodes always pause and wait for an ACTION_ID response.
O_SELECT_MODE: Opens a modal for branching logic. (ID Range:570+)O_COLOR_SELECT: Opens a color picker. (ID Range:580-585)O_TAP_O: Requests selection of an opponent's stage slot. (ID Range:600-602)
3. Dynamic Choices (Context Dependent)
These opcodes may skip interaction if only one valid target exists, or if certain attributes are set.
O_PAY_ENERGY:- Automatic: If no optional bit is set, it auto-taps.
- Interactive: If
attr & 0x82is set, it asks "Pay Energy?" (ID Range:550-551).
O_LOOK_AND_CHOOSE(List Selection):- Opens a card list overlay. (ID Range:
600+)
- Opens a card list overlay. (ID Range:
O_TAP_M:- Automatic: If selecting "Self" or only one member.
- Interactive: If
attr & 0x02is set, it asks for a specific member.
Action ID Reference Table
| Range | Context | Usage |
|---|---|---|
0 |
Global Skip | Discard remaining looked cards, skip optional cost, "No" to promt. |
500-559 |
Hand | Selecting a card currently in hand. |
560-569 |
Generic | Resumption signals. |
570-579 |
Modal Mode | Choosing Option A/B/C from SELECT_MODE. |
580-585 |
Modal Color | Pink(0), Red(1), Yellow(2), Green(3), Blue(4), Purple(5). |
600-602 |
Stage Slots | Left, Mid, Right (Self or Opponent). |
600-659 |
List Index | Choosing the N-th card in a "Looked Cards" or "Discard" list. |
Resumption Logic in interpreter.rs
When an opcode calls suspend_interaction, the following happens:
state.phaseshifts toPhase::Response.- A
PendingInteractionis pushed to the stack containing theprogram_counter(IP) of the CURRENT instruction. - The engine returns controle to the caller.
- The caller (Frontend/Server) must send a
step(action_id)call to resume. resolve_bytecoderestarts from the stored IP, injecting theaction_idintoctx.choice_index.
State Transparency (The Visibility Gap)
The following engine states are not currently surfaced through the main Action serialization:
| Gap | Description | Impact |
|---|---|---|
| Passive Stats | Constant power/blade buffs from other members. | Card value in sidebar might not match calculated logic. |
| Queue Depth | How many abilities are still waiting to resolve. | Player doesn't know "one more popup is coming". |
| Filter Logic | Why a specific card is selectable (or not). | Debugging complex filters (e.g., "Member of Unit X with Cost >= 3"). |
| Progress Count | "Pick 1 of 3" status during multi-picks. | Action label is generic (e.g., "Select Slot 1"). |
Recommended Verifications
- For Passives: Manually inspect
player.blade_buffsorplayer.heart_buffsin the engine log. - For Filters: Cross-reference the
filter_attrbitmask withlogic.rs:card_matches_filter. - For Queue: Check
gs.pending_abilities.len()in the debugger.