byo.games

Game format

game.toml

[game]
name = "my-game"          # kebab-case identity
console = "0.4"
players = 1               # declared seats, 1..8
goals = ["reach the end"] # completable via byo.complete
# orientation = "portrait"       # 432×768 phone mount (default landscape)
# palette = "assets/palette.pal" # optional

[controls]
# the touch overlay renders exactly what you declare — keep it honest
buttons = ["a", "b"]      # from: a b x y l r ([] = dpad only)
# dpad = false   pointer = true   text = true   overlay = "off"

players bounds the input fabric: btn(name, seat) beyond the declared count is an error, replays carry one |-separated column per seat, and verification storms every declared seat. overlay = "off" opts a game out of the touch pad entirely (players can still force it with ?touch=1).

Palette

assets/palette.pal: up to 32 lines of name #rrggbb (comments with # at line start). Game code sees P.name → index. Index 255 is transparent in sprite data. Without a palette file the default 32-color set loads.

Reserved files

  • bots/*.lua — sandboxed _input(view) controllers, the game's proof-of-play. Bundled, outside the source budget, not require-able.
  • checks.lua — the logic-test suite byo test runs; publishing runs it, and failing checks fail the version.

Budgets (enforced by byo check and at submit)

budget limit
source (all .lua except bots/ + checks.lua) 48,000 tokens (estimator v1: ceil(bytes/4))
assets + data 16 MB
bundle (.byo) 32 MB
palette 32 colors

The source budget is the point: the whole game always fits in one context window, no matter how many versions it has been through.

Bundles

byo bundle --game mygamemy-game.byo, a store-only (uncompressed) zip of the game directory (excluding out/) — source, assets, replays, bots, and checks together. Inspectable with any zip tool; the venue extracts, re-checks, re-tests, and re-verifies every bundle it receives.

Conventions that make games agent-friendly

  • Keep state in globals (auto-snapshotted; a single G table is tidiest).
  • Structured reads beat log-scraping: byo dump --expr "G" (or the dump tool) prints canonical JSON; dump --view N prints what seat N may know.
  • Games with hidden information define _view(seat) — it is the fairness boundary for bots and the wire contract if a thin client ever exists.
  • Fire byo.complete when a goal is genuinely earned. If gameplay changes, re-record the completion replay with a bot: stale replays stop verifying.