Documentation
¶
Overview ¶
Package smoke is the engine behind the public smoke package and the dev runner's -smoke mode: it parses a game's smoke.yaml, executes the script deterministically against a native game (virtual clock, seeded RNG), and renders the named shots. The devkit CLI runs the same script against the built wasm artifact and renders through the same encoder, so a deterministic game produces byte-identical shots on either path.
Index ¶
Constants ¶
const DefaultHeartbeat = 50 * time.Millisecond
DefaultHeartbeat is the wake cadence used when smoke.yaml omits heartbeat — matching the dev runner's default.
Variables ¶
This section is empty.
Functions ¶
func MainCLI ¶
MainCLI is the `go run . -smoke …` entrypoint: parse the script, run it, write the shots, report. Exits non-zero on any error.
func RenderANSI ¶
RenderANSI renders a frame to the shot file form: 24 truecolor ANSI lines, LF separators, trailing newline. This is the canonical byte form — the devkit CLI's wasm path renders through the same encoder.
func RenderText ¶
RenderText renders a frame as plain text: full grapheme clusters, no escape sequences, trailing blanks trimmed — the greppable twin of RenderANSI.
func Wants ¶
Wants reports whether the dev-runner invocation asks for smoke mode — a `-smoke` (or `--smoke`, `-smoke=…`) argument anywhere on the command line. kit.Main dispatches here before the interactive runner so `go run . -smoke smoke.yaml` needs no terminal.
func WriteShots ¶
WriteShots writes each shot's .ansi and .txt files into dir (created if missing): NN-<name>.{ansi,txt} when the shot collapses (single seat, or all captured frames identical), NN-<name>.seat<K>.{ansi,txt} otherwise. It returns the written file names, in order.
Types ¶
type Script ¶
type Script struct {
Seed int64
Seats int
Heartbeat time.Duration
Config map[string]string
Steps []Step
}
Script is a parsed smoke.yaml: the deterministic inputs (seed, seats, config) plus the ordered steps that drive the game and name the shots.
type Shot ¶
type Shot struct {
Ordinal int // 1-based shot index within the script
Name string // the `shot:` name
Seats []int // captured seat indices, ascending
Frames []*game.Frame
}
Shot is one captured screen dump: the frames of every captured seat at the moment the shot step ran. When every captured frame is identical (broadcast games) the shot collapses to a single unsuffixed file.
func Run ¶
Run executes a parsed script against the game natively: a virtual-clock, seeded room (no terminal, no wall clock) mirroring the dev runner's -seed semantics. All seats join before the first step; `advance` moves the clock one heartbeat at a time, waking the game after each increment; shots capture the latest frame sent to each captured seat.
Identities are the smoke contract shared with the devkit CLI's wasm path: seat i is AccountID "seat-<i>", Handle "seat<i>", member kind. The room is ModeSolo for one seat and ModePrivate otherwise, with Capacity = seats.
type Step ¶
type Step struct {
Kind StepKind
Line int
Rune rune // StepRune
Key game.Key // StepKey
Seat int // StepSeat target
D time.Duration // StepAdvance
Name string // StepShot name
Seats []int // StepShot filter; nil = all seats
}
Step is one parsed script step. Line is the smoke.yaml source line, kept for error reporting during the run.
type StepKind ¶
type StepKind uint8
StepKind enumerates the script step vocabulary.
const ( // StepRune delivers a printable rune to the current seat (`rune:`, and // each character of a `text:` step). StepRune StepKind = iota // StepKey delivers a named key to the current seat (`key:`). StepKey // StepSeat switches the current input seat (`seat:`), sticky. StepSeat // StepAdvance sweeps the virtual clock forward, waking the game once per // heartbeat (`advance:`). StepAdvance // StepWake delivers a single wake without moving the clock (`wake:`). StepWake // StepShot captures the current screen of every captured seat (`shot:`). StepShot )