Replays
A replay is a text file: a seed plus an input timeline. Because the console is deterministic, replaying it reproduces the exact game — which makes a replay simultaneously a regression test, a proof of completion, and a watchable recording.
Format
game: my-game
seed: 0
goal: reach the end
-- timeline: "<frame> <buttons…>", held until the next line
0 right
40 right a
120 -
- Frames are absolute and ascending. Buttons:
up down left right a b x y l r start select.-= nothing held. - The listed state is held until the next line changes it.
- N players:
|separates seat columns — column i is seat i (12 right a | left | - | a). A line updates only the columns it lists; omitted trailing columns keep their held state, and-explicitly clears one. - Pointer: a
p:x,y,buttonstoken (held until the nextp:token):30 a p:384,216,1. Text typed on exactly that frame:t:<hex utf-8>. Device tokens live in column 1. goal:names the game.toml goal this replay claims to complete.
Verification
byo verify replays/win.rpl --game mygame
re-simulates the replay; the declared goal must fire (byo.complete)
before the timeline ends (+60 frames of grace), and the game must pass
the snapshot test (save, simulate garbage, restore — the future must be
bit-identical). A game is publishable only while at least one bundled
replay verifies. The site re-runs this on its own servers for every
published version.
Recording
- The right way is a bot (below): the sim records what it presses.
- The browser watch pages replay any bundled
.rpl— the replay drives every seat, keyboard and touch off.
Bots — authoring replays closed-loop
Hand-computing frame timings is the hard way. Write a controller instead — sandboxed, one per seat, reading a view, never the globals:
-- bots/seek.lua: _input(view) returns the buttons to hold next frame.
-- view = what this seat may know: the game's _view(seat) if defined,
-- else the game's save (its state as one data table).
function _input(view)
if view.G.player.x < view.G.sword.x then return "right" end
return ""
end
Bots live in the reserved bots/ directory (bundled with the game,
outside the source budget). Run one per seat inside the real sim:
byo sim --bot bots/seek.lua --record replays/win.rpl
byo sim --bot 1:bots/hero.lua --bot 2:bots/rival.lua --record replays/vs.rpl
(or the bot tool over the API, with bots: [{seat, path | source}]).
The sim records every seat's presses as a normal N-column replay; if a
goal completes, the header is written and the replay verifies as-is.
Replays authored by sandboxed bots against a game-defined _view carry a
fair: seat N stamp — provenance that the run played by the same
information rules a person would. --god (debug only) loads a bot inside
the game env; god recordings never earn the stamp.
Bots run only during authoring — verification re-runs the recorded inputs without the bots, so a bot that mutates game state produces a replay that fails. Read the view, return buttons, nothing else.
The verify horizon
Verification simulates to the last input frame + 60. A two-line replay ends
after ~60 frames even if the game needed thousands — pad the end
(2400 -) to extend the run.