TECHNOLOGY

Why the runtime
isn’t a language model.

How Mekyra represents rules, what the engine guarantees, what building a multiplayer rules engine taught us, and why Claude works on the rules but never inside the match.

THE OBVIOUS QUESTION

Why not just ask Claude
to code the game?

Ask a coding assistant for a card game and you’ll get one. For a small game with a few rules, that may be all you need.

What you don’t get is a model of the rules. The rules exist only as code, and each mechanic is implemented wherever and however it happened to be generated. At twenty cards that’s manageable. At two hundred, with triggers that fire other triggers, targets that change sides and choices that wait on another player, nobody can say for sure what the game does, including the assistant that wrote it.

Mekyra separates the two. Rules are data written in a fixed vocabulary. One engine interprets that data, and it’s the same engine for every rule and every game. Claude’s role is authoring, the layer we’re building now on top of the engine: it proposes rule definitions and test scenarios instead of game code, and both can be checked before anything runs.

In short: a coding assistant generates application code. Mekyra maintains a persistent formal model of the rules, executes it through one deterministic runtime, and validates and tests it reproducibly.

ONE RULE, END TO END

From a sentence
to a state transition.

The same rule at three stages. The DSL is illustrative: the real syntax is still being designed as part of generalizing the engine.

1 · Written ruleINPUT
“When this creature enters play, deal 2 damage to an opposing creature on an adjacent lane.”

Claude flags a question before anything is compiled:
“Adjacent to this creature’s lane, or any lane next to it on the opponent’s side?”

2 · Structured ruleIllustrative DSL
TRIGGER: ENTER_PLAY (self)

TARGET:
  TYPE: CREATURE
  CONTROLLER: OPPONENT
  LANE: ADJACENT_TO(self.lane)
  CHECK_AT: SELECT, RESOLVE
  IF_NONE: SKIP_EFFECT

EFFECT:
  DAMAGE: 2
3 · Deterministic state transitionENGINE
state_041
opponent lane 1: Creature (HP 5) · your lane 2: empty
action
player 1 plays this creature to lane 2
event
ENTER_PLAY(self) → rule triggers
targets
opponent creatures in lanes 1 and 3 → [Creature, lane 1]
choice
one legal target, so no prompt is shown
effect
DAMAGE(Creature, 2)
state_042
opponent lane 1: Creature (HP 3)

Replay state_041 with the same action and you get the same state_042, on any server, every time.

DETERMINISM

Same state, same action,
same result.

The engine is built as a function from (state, action) to the next state, with no hidden inputs: no wall-clock time, no network calls, no model inference. Randomness comes from a seeded RNG stored in match state, and every random operation is logged, so a replay can be checked against the original draws.

That one constraint pays for a lot. A test is just a saved state, an action and an expected result. A match can be replayed from its action log. A server can validate a client’s move by running it. A bug report can include the exact state where it happened.

STATE MODEL

What a match is made of.

A match state holds the zones and the objects in them, who owns and who controls each object, counters and modifiers, whose turn it is, effects waiting to resolve, and any choice a player still has to make.

Nothing a match depends on lives only in a client. That’s what lets the server validate every move and lets any player reload and pick up exactly where the match is.

RULES VS CODE

The DSL is deliberately
small.

The Game Rules DSL describes triggers, conditions, targets, choices, costs, effects, durations, zones, ownership and control. It can’t express arbitrary code, and that’s the point: anything it can express, the engine can execute and the validator can check.

When a mechanic doesn’t fit, that’s a signal. Either the rule needs clarifying or the vocabulary needs a new, general building block that every game then gets. It never becomes a one-off patch hidden in a card’s implementation.

VALIDATION

Two kinds of checks.

At runtime, every action is checked by the engine on the server: is it this player’s decision, is the card where it should be, is the target legal right now. In the private prototype, legal targets come from the authoritative engine layer, and the same legality system is used wherever the server checks an action.

At authoring time, the model itself gets checked before any match runs: targets that can’t exist, effects that reference missing zones, ownership checked at the wrong moment. These static checks are planned.

REPRODUCIBLE TESTS

Tests are states, not scripts.

A test sets up a known state, applies one action and asserts on the result. Because the engine is deterministic, a test that passes once passes every time, and a failing test points at a specific rule and a specific state.

given   state_041
when    player_1 plays creature to lane 2
expect  opponent.lane[1].creature.hp == 3
expect  pending_choices == []

The engine already has automated tests, including complex multi-effect interactions. Generating scenarios like this one from the rules, with Claude proposing the edge cases, is in development.

WHAT THE PROTOTYPE TAUGHT US

Problems you only meet
by running real matches.

The architecture on this page came out of building a multiplayer rules engine for a dense card game, not out of a whiteboard. These are the cases that shaped it.

  1. 01

    A choice outlives a connection

    A player can drop out while choosing a target, with an effect half-resolved and other players waiting.

    Pending choices are match state, not UI. On reconnect the same decision is waiting, and the effect resolves once.

  2. 02

    Targets go stale

    Between choosing a target and resolving the effect, another effect can remove it.

    Legality is checked when the target is chosen and again at resolution, under a rule the designer sets.

  3. 03

    Control changes mid-effect

    “Opposing creature” means something different if the creature switches sides while an effect waits.

    Ownership and control are evaluated at a defined timing point, the same one every time.

  4. 04

    Triggers pile up

    One action can set off several triggered abilities, some of which ask players for choices.

    Triggers that fire together are put in a deterministic order and resolved one by one, so the result never depends on which client or network message arrived first.

  5. 05

    Whose decision is it?

    In a multiplayer match the player whose turn it is isn’t always the one who has to decide.

    Every pending decision has an owner. The server rejects answers from anyone else, and answers to a decision that is no longer current.

  6. 06

    Durable versus fast

    Saving state on every action makes reconnect and replay easy, and adds work to every move.

    For turn-based play durability wins. Live games may want a different trade, which is where runtime profiles come in.

RUNTIME PROFILES · DIRECTION

Same rules model,
different runtime needs.

A turn-based match that lasts days and a live head-to-head game need different things from the server. The plan is one rules model and one engine, with the synchronization and storage strategy chosen per game. Neither profile is a finished mode today.

Durable

Planned

For games where a match must survive anything.

  • Server-authoritative state, saved as the match progresses
  • Long disconnects, page reloads, switching devices
  • Turn-based matches that resume hours or days later
  • Reliability ahead of minimum perceived latency

Live

Planned

For games where players are present at the same time.

  • Fast state synchronization over a persistent connection
  • Presence: who is connected, who is deciding
  • Near-immediate updates after every action
  • Persistence tuned so it doesn’t sit in the hot path

WHERE CLAUDE FITS

Useful for reading.
Kept out of the match.

Language models are good at text and bad at guaranteeing the same answer twice. So Claude works on the rules before the game runs, and the engine handles everything after.

Claude does not decideDURING A MATCH
  • Whether an action is legal
  • Which targets are valid
  • How much damage is dealt
  • What the next game state is
  • Who wins
Claude helps withWHILE AUTHORING
  • Reading rulebooks, FAQ and errata
  • Finding entities, triggers, conditions and effects
  • Spotting ambiguous wording and asking about it
  • Proposing a structured version of each rule
  • Writing edge cases and explaining interactions
THE RUNTIME CONTRACT
Same state
+
Same action
=
Same result
state_041actionstate_042

That’s what makes replay and reproducible tests possible.

WHY THE RUNTIME ISN’T LLM-DRIVEN

A game you can’t replay
is a game you can’t debug.

If a model decided outcomes during play, the same move could resolve differently on two runs. Tests would be flaky by design, two players could see different states, and nobody could answer “why did that happen?” with certainty.

Keeping the runtime deterministic is what makes multiplayer, reconnect, persistence, replay and server-side validation straightforward instead of heroic.

CONTACT

Working on a game
with a lot of rules?

Tell us what you’re building and where the rules get difficult.
Early conversations with designers decide what the general engine supports first.

Email Mekyra [email protected]Mekyra is in private development. Every email is read by the founder.