Documentation
¶
Overview ¶
Package proto is the protocol between the host (internal/ui and internal/proto/host) and every "program" it runs: the persona, each game, the ending and the movie director.
A program never touches the terminal. It receives Events, returns Outputs, and draws into a Canvas of semantic styles. It must not block: anything slow (an AI search, a brain reply) is returned as a Think output and runs off the UI goroutine.
The package depends on the standard library only.
Index ¶
- Constants
- Variables
- func GameStream(slug string, playIndex uint16) uint64
- func NewRand(seed, stream uint64) *rand.Rand
- type Animate
- type Attr
- type AwaitKeys
- type Canvas
- type Cell
- type Clear
- type Done
- type Drain
- type Drained
- type Env
- type Event
- type GameOver
- type Hold
- type Key
- type KeyEvent
- type Launch
- type Layout
- type Limit
- type LineEvent
- type Outcome
- type Output
- type Pace
- type Program
- type Prompt
- type Quit
- type Redraw
- type ResizeEvent
- type Result
- type Say
- type SetLayout
- type Skip
- type Style
- type Think
- type ThinkDone
- type TickEvent
- type Wait
Constants ¶
const ( DomainBrain uint64 = 1 << 56 // id: brain turn DomainGame uint64 = 2 << 56 // id: hash32(slug)<<16 | play index DomainAI uint64 = 3 << 56 // id: think sequence number DomainMovie uint64 = 4 << 56 // id: scene number DomainUI uint64 = 5 << 56 // id: 0 )
Stream domains keep every consumer's random sequence separate. A StreamID is Domain<<56 | id.
Variables ¶
var ErrCanceled = errors.New("cancelled by the user")
ErrCanceled is ThinkDone.Err when the user cancelled the request (Esc while a brain reply was pending).
Functions ¶
func GameStream ¶
GameStream returns the stream id for the playIndex-th game of slug in a session.
Types ¶
type AwaitKeys ¶
AwaitKeys switches to key mode; KeyEvents follow until the next Prompt.
Capture is for a root program other than the persona (the movie director): it then receives every key, Esc included (KeyEsc), with none of the host's side effects: no key skips the typewriter and Esc is not the host's. While a program it launched runs, keys other than Ctrl+C do nothing. The host ignores Capture from a launched program.
type Canvas ¶
type Canvas struct {
W, H int
// contains filtered or unexported fields
}
Canvas is a fixed-size grid of cells that programs draw into. Every rune occupies one cell; art is ASCII by design.
func (*Canvas) Put ¶
Put writes s starting at x, y in one style, clipping at the edges. It returns the x after the last rune written.
type Clear ¶
type Clear struct{}
Clear starts a new page. Scrollback keeps what was above it. The host starts one by itself when it launches a program whose layout is not LayoutConsole (see Launch).
type Done ¶
type Done struct{ Result Result }
Done pops this program; the one below receives GameOver.
type Drain ¶ added in v0.2.0
type Drain struct{}
Drain asks for a Drained event once everything output before it has been revealed and its pauses waited out, so a program can pace itself one step at a time (movie mode). A newer Drain replaces a pending one, and only the running program hears it.
type Drained ¶ added in v0.2.0
type Drained struct{}
Drained answers a Drain: the output before it has been revealed.
type Env ¶
type Env struct {
Seed uint64 // derive random streams with NewRand(Seed, StreamID)
Width, Height int // the program's layout area, always at least its minimum
Instant bool // no pacing: --instant, tests
Deterministic bool // --seed or WOPR_SEED, tests, movie mode: searches obey Limit, not the clock
ReduceMotion bool // --reduce-motion: no acceleration, no blinking
Mode string // optional launch mode, e.g. "climax"
}
Env is what a program learns about its surroundings when it starts.
type Event ¶
type Event interface {
// contains filtered or unexported methods
}
Event is something the host tells a program. The set is closed.
type GameOver ¶
type GameOver struct{ Result Result }
GameOver tells a program that the program it launched has finished.
type Hold ¶ added in v0.2.0
type Hold struct{ On bool }
Hold freezes output while On: the typewriter, Wait, Animate and Blink stop where they are, as they do behind the TERMINAL TOO SMALL card, until a Hold with On false (movie mode's pause). Keys still arrive, but none reveals held output, and neither does Env.Instant. Only a root program that captures keys (AwaitKeys.Capture) can hold output, since it alone is sure to get the key that releases it; the host ignores Hold from any other program. A hold ends when its program launches another or ends.
type Key ¶
type Key uint8
Key is a key a program can receive in key mode. Esc belongs to the host: only a root program that captures keys (AwaitKeys.Capture, movie mode) receives KeyEsc.
type KeyEvent ¶
KeyEvent is a key press, delivered only in key mode (after AwaitKeys). KeyEsc arrives only at a root program that captures keys.
type Launch ¶
type Launch struct{ Slug, Mode string }
Launch pushes another program on top of this one. A program with its own screen (any layout but LayoutConsole) starts on a new page, whether it was launched or handed off to, so its console strip shows only its own text. Ending a program does not start one: its last lines stay above the verdict.
type LineEvent ¶
type LineEvent struct{ Text string }
LineEvent answers the last Prompt. Text is sanitised and trimmed; "" is an empty Enter.
type Output ¶
type Output interface {
// contains filtered or unexported methods
}
Output is something a program asks the host to do. The set is closed: every output a program can produce is declared in this file.
func Typed ¶ added in v0.2.0
Typed returns the outputs that show a user typing text after prompt, laid out as the console echoes an answer: the prompt at once, a pause, the text a few keystrokes at a time at PaceTyping on the same row, then a blank line. r jitters the pauses and the bursts (movie mode seeds it); with nil every keystroke is its own burst and the pauses are fixed. Under Env.Instant the host drops the pauses, so the line appears whole.
type Pace ¶
type Pace uint8
Pace is how fast the typewriter reveals text.
const ( PaceSpeech Pace = iota // WOPR speaking, about 30 characters per second PaceTable // tables and lists, fast PaceInstant // boards and redraws, no delay PaceTyping // a simulated user typing (movie mode), about 8 characters per second )
Paces.
func (Pace) CharsPerSecond ¶
CharsPerSecond returns the typewriter speed for p; 0 means instant.
type Program ¶
type Program interface {
// Start is called once, after the first valid terminal size is known.
Start(Env) []Output
// Handle reacts to one event. It must return quickly.
Handle(Event) []Output
// View draws the program's layout area. It is never called for LayoutConsole.
View(c *Canvas)
}
Program is implemented by the persona, every game, the ending and the movie director.
type Prompt ¶
type Prompt struct{ Text string }
Prompt switches to line mode; the next LineEvent answers it.
type ResizeEvent ¶
type ResizeEvent struct{ Width, Height int }
ResizeEvent reports a change of the program's layout area.
type Result ¶
type Result struct {
Outcome Outcome
Lines []string // kill ratios and other detail for the persona's verdict
Next *Launch // hand-off without a verdict, e.g. gtw → tictactoe(climax) → ending
NoVerdict bool // the persona adds nothing after this program's last line
}
Result is reported by Done.
type Say ¶
Say prints lines through the typewriter. With Open, the last line stays open: the next Say continues it on the same row, as a typist's keystrokes do (movie mode, Typed).
type Skip ¶ added in v0.2.0
type Skip struct{}
Skip reveals at once everything output before it, as a key press skips the typewriter (movie mode's next and previous scene). It reveals held output too.
type Style ¶
type Style uint8
Style is the meaning of a cell, not its colour. The ui maps each Style to the active theme, with explicit 16-colour and no-colour fallbacks.
const ( StyleText Style = iota StyleBright StyleDim StyleAccent StyleLand StyleLabel StyleIncoming StyleOutgoing StyleTarget StyleDefcon1 StyleDefcon2 StyleDefcon3 StyleDefcon4 StyleDefcon5 StyleAlert StyleSuitRed StyleSuitBlack StyleSelected )
Styles.
type Think ¶
Think runs Fn off the UI goroutine and delivers its result as a ThinkDone event.
Fn must use only values it captured (copy positions, e.g. as a FEN string): the program keeps running while Fn does. With Env.Deterministic, Fn must stop at Limit; Budget is a safety cap. Otherwise Budget is the main bound: when the context's deadline passes, Fn returns the best result it has, without an error.
type ThinkDone ¶
ThinkDone carries the result of the program's Think. A program has at most one Think in flight: a new Think replaces the previous one, whose result is dropped. Err is ErrCanceled when the user cancelled the Think with Esc and the program keeps running (a brain reply at the root); a confirmed abort pops the program, so its result is never delivered. For a search, a deadline is not an error (Fn returns its best result); slow I/O such as a brain reply returns an error instead.