Skip to content

Actions ​

Actions are the engine's explicit state transition commands. They are the only way the game state can be modified during the phases defined in your Flow of Time. Actions can be taken to modify entities, zones, or a combination of both.

By adhering to a strict declarative structure, Actions replace "magic scripts" with explicit mathematical mutations mapping inputs to state outcomes.

Defining Actions ​

Actions can be contextualized in two locations:

  1. Global Actions: Actions defined at the root that can be called by players generally (e.g., PlayCard, PassTurn, MovePiece).
  2. Entity Actions: Actions distinctly tied to an entity that an entity is capable of executing (e.g., a potion's Consume or a character's Heal).

Anatomy of an Action ​

An Action definition requires:

  • name: The identifier used in phase valid_actions whitelists.
  • requires_target: (Optional) Restricts what the player must select before executing the action.
  • mutations: An array of explicit operations modifying the state of properties or zone locations.
yaml
actions:
  - name: PlayCard
    requires_target: $zone.@MainBoard
    mutations:
      - target: $entity.selected
        destination: $target.zone
        operation: MoveZone
      - target: $player.current
        property: mana
        operation: -
        value: $entity.selected.cost
json
{
  "actions": [
    {
      "name": "PlayCard",
      "requires_target": "$zone.@MainBoard",
      "mutations": [
        {
          "target": "$entity.selected",
          "destination": "$target.zone",
          "operation": "MoveZone"
        },
        {
          "target": "$player.current",
          "property": "mana",
          "operation": "-",
          "value": "$entity.selected.cost"
        }
      ]
    }
  ]
}

:::

Mutations ​

Mutations declaratively explain the absolute mathematical change requested by the action.

Common operations include:

  • = (set)
  • + (add)
  • - (subtract)
  • MoveZone (change an entity's parent zone)
  • Destroy (remove an entity from the game)

Mutating Entities and Zones ​

You can modify combinations of entities and zones inside a single action.

yaml
entities:
  - id: HealingPotion
    type: card
    actions:
      - name: Consume
        requires_target: $entity.piece
        mutations:
          # Mutates an entity's property
          - target: $target.entity
            property: current_health
            operation: +
            value: 2
          # Mutates a zone (by moving the entity to a new zone)
          - target: $entity.self
            destination: $zone.@DiscardPile
            operation: MoveZone
json
{
  "entities": [
    {
      "id": "HealingPotion",
      "type": "card",
      "actions": [
        {
          "name": "Consume",
          "requires_target": "$entity.piece",
          "mutations": [
            {
              "target": "$target.entity",
              "property": "current_health",
              "operation": "+",
              "value": 2
            },
            {
              "target": "$entity.self",
              "destination": "$zone.@DiscardPile",
              "operation": "MoveZone"
            }
          ]
        }
      ]
    }
  ]
}

Reactions (Interrupts & Responses) ​

Rather than having a disconnected "Listener" concept, your actions and entities natively hold the reaction information. When an entity is capable of reacting to an opponent's move or an engine engine hook, you declare reactions inside an action or an entity. This explicitly yields priority to another player or system to take a specific action (such as playing a Trap Card, casting a Counterspell, or applying an Armor buff).

Reactions use a trigger lifecycle hook (Before or After) to determine when they interrupt typical flow.

yaml
entities:
  - id: IronArmor
    type: equipment
    reactions:
      - name: PreventDamage
        trigger: $Before.$DamageTaken
        condition: $entity.self.is_equipped == true
        mutations:
          - target: $event.damage_value
            operation: -
            value: 1

  - id: TrapCard
    type: card
    actions:
      - name: Counterspell
        reactions:
          - trigger: $Before.$ActionPlayed
            condition: $event.action.type == 'spell'
            mutations:
              - target: $event.action
                operation: Cancel
json
{
  "entities": [
    {
      "id": "IronArmor",
      "type": "equipment",
      "reactions": [
        {
          "name": "PreventDamage",
          "trigger": "$Before.$DamageTaken",
          "condition": "$entity.self.is_equipped == true",
          "mutations": [
            {
              "target": "$event.damage_value",
              "operation": "-",
              "value": 1
            }
          ]
        }
      ]
    },
    {
      "id": "TrapCard",
      "type": "card",
      "actions": [
        {
          "name": "Counterspell",
          "reactions": [
            {
              "trigger": "$Before.$ActionPlayed",
              "condition": "$event.action.type == 'spell'",
              "mutations": [
                {
                  "target": "$event.action",
                  "operation": "Cancel"
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

Triggered Actions ​

Unlike a background effect or a forced reaction, a Triggered Action is an engine-prompted opportunity for a player to take a specific action after another action occurs, assuming specific conditions are met.

Common use cases include explicit follow-up choices, like responding to a specific play with an optional ability, or chaining abilities together. You define these using the triggered_actions block.

When a trigger fires, the engine automatically grants temporary priority to the eligible player. By defining optional: true (which is the default), the engine presents the player with the choice to either accept or decline executing the action. If optional: false is set, the action forces the player to resolve it (potentially requiring targets or specific choices).

yaml
triggered_actions:
  - name: EnPassant
    trigger: $After.@MovePiece
    condition: >
      $event.entity.tags.contains('Pawn') and
      $event.action.distance == 2
    optional: true
    requires_target: $event.entity
    mutations:
      - target: $target.entity
        destination: $zone.@Graveyard
        operation: MoveZone
      - target: $entity.self
        destination: $event.entity.passed_location
        operation: MoveZone
json
{
  "triggered_actions": [
    {
      "name": "EnPassant",
      "trigger": "$After.@MovePiece",
      "condition": "$event.entity.tags.contains('Pawn') and $event.action.distance == 2",
      "optional": true,
      "requires_target": "$event.entity",
      "mutations": [
        {
          "target": "$target.entity",
          "destination": "$zone.@Graveyard",
          "operation": "MoveZone"
        },
        {
          "target": "$entity.self",
          "destination": "$event.entity.passed_location",
          "operation": "MoveZone"
        }
      ]
    }
  ]
}
    }
  ]
}

] }


:::

::: tip Functional Asynchronicity
By pushing trap-cards and continuous lifecycle rules into the object's `reactions`, priority is explicitly yielded to other actors, resolving complex interactions structurally without messy UI scripting!
:::

::: tip Strict Contracts
Because the engine only evaluates exactly the mutations you array inside an action, you never have to worry about an action producing a silent side-effect elsewhere in your game!
:::

## Appendix: Operations & Triggers Reference

### Valid Mutation Operations
When defining an action's `mutations`, the `operation` key must utilize one of the following:

**Arithmetic Operations:**
- `=`: Set explicit value.
- `+`: Addition assignment.
- `-`: Subtraction assignment.
- `*`: Multiplication assignment.
- `/`: Division assignment.

**Engine API Operations:**
- `MoveZone`: Reparents the entity (requires a `destination` key).
- `Destroy`: Deletes the entity entirely from all memory blocks.
- `Cancel`: Negates an event stack item entirely (used specifically during React/Response priority shifts).
- `SetProperty`: Modifies an explicit dynamic trait.
- `RequireDiscard`: Demands a user discards generic elements from a set.
- `Promote`: Alters an entity's internal identity explicitly.
- `DrawCard`: Moves the `0` index item from a stack deck to a player's hand space.

### Valid Reaction Triggers
When placing a `reaction` structure on an entity or an action intercept, you must hook into the priority state loops using standard `Before` or `After` prefixes.

Available lifecycle events:
- `Before.DamageTaken` / `After.DamageTaken`
- `Before.OnZoneEnter` / `After.OnZoneEnter`
- `Before.ActionPlayed` / `After.ActionPlayed`
- `Before.PhaseExecute` / `After.PhaseExecute`