package inkbase

import "git.teletypegames.org/engines/inkwell/inkbase"

Package inkbase is the generic foundation of inkwell: the registries, text in several languages, world state, the action and condition framework and the data types any Ebitengine game can build on without pulling in adventure-game machinery — no scenes, characters, dialogs or verbs. This package itself is pure Go with no dependency beyond the standard library; its sub-packages import Ebitengine only where they must.

The root inkwell package builds on these types and re-exports them, so an adventure imports inkwell alone; a game that is not an adventure imports inkbase and the sub-packages it needs.

What is here

Sub-packages

The Ebitengine services are font (the glyph atlas and text drawing), input (consume-on-use input polling), asset (the filesystem, the image cache and the audio player) and transition (how one picture gives way to another, and the fade). stage holds the Stage, one full-screen thing a game shows. The framework packages are action (the generic actions and combinators), condition (the generic conditions) and widget (the Widget contract, layers, ordering and the ClickBlocker contract). The widgets are menu, panel, textcard, keybinding, letterbox, endcard, statusline, topbar and chatlog.

A widget, an action or a condition reaches its game through an exported host interface it type-asserts the UICtx's or the Ctx's Game to — a widget package's is called Host, and most embed widget.Screen. The host interfaces are listed in each package. inkwell's *Game satisfies all of them, so the root package re-exports these widgets and types rather than carrying its own; a game built on inkbase alone implements the hosts of the pieces it uses.

Index

Variables

var Fallback string

Fallback is the language used when a Text says nothing in Lang.

var Lang string

Lang is the language the game speaks. Empty means every Text falls through to Fallback, and then to the language it was authored in.

Types

type Action

type Action interface {
	Start() Runner
}

Action is an immutable spec of work; Start makes a fresh Runner with state. Storing an Action in a struct field is safe because the engine always calls Start before ticking, so two invocations can never share mutable state.

type Align

type Align int

Align controls horizontal text alignment for widgets that draw a single line.

const (
	AlignLeft   Align = iota // flush with the left edge
	AlignCenter              // centered
	AlignRight               // flush with the right edge
)

The horizontal alignments.

type Asset

type Asset struct {
	Name string
	Path string
}

Asset is a picture on the asset filesystem: a scene's background, a stage's, a sprite.

func (Asset) GetName
func (a Asset) GetName() string

GetName returns the asset's Name, its key in the registry.

func (Asset) TypeLabel
func (a Asset) TypeLabel() string

TypeLabel returns "asset", the kind used in log and panic messages.

type Audible

type Audible interface {
	Source() string
}

Audible is anything an audio player can play: a file on the asset filesystem, named by Source.

type Condition

type Condition interface {
	Eval(ctx *Ctx) bool
}

Condition is a question about the game as it stands: a flag, a variable, the stage showing. Actions branch on one, widgets are shown by one, and a dialog choice is offered by one.

type Ctx

type Ctx struct {
	DT    float64
	State *State
	Game  any
}

Ctx is the per-tick context passed to running actions. State is available directly — most generic actions only need it. Game is opaque; an action needing more (audio, stages, themes) type-asserts it to a narrow host interface. Adventure actions assert it to *Game.

type Delivery

type Delivery int

Delivery is how a speaker reaches the player: over the scene as a speech bubble, or through the message log alone.

const (
	DeliveryBubble Delivery = iota // speech bubble over the scene, plus the log
	DeliveryLog                    // the log alone
)

The ways a voice can be delivered.

type Knowable

type Knowable interface {
	Named
	TypeLabel() string
}

Knowable is an entity the player can come to know — an Item, a Character, a Speaker — and so an entry a dossier or a codex screen can list. The kind is part of the key, so an item and a character may share a Name.

type LogKind

type LogKind int

LogKind classifies a chat-log entry — UI widgets style them differently.

const (
	LogAction   LogKind = iota // player command ("> look at door")
	LogResponse                // in-world reply / Say output
	LogSystem                  // game/system message
)

The kinds of chat-log entry.

type LogMessage

type LogMessage struct {
	Speaker string // empty for actions / system
	Text    string
	Kind    LogKind
}

LogMessage is a single line in the chat-log buffer.

type Manager

type Manager[T Named] struct {
	// contains filtered or unexported fields
}

Manager is the single registry shape used by every entity type. Insertion order is preserved — Names() and All() both hand it back.

func NewManager
func NewManager[T Named]() *Manager[T]

NewManager returns an empty registry for entities of type T.

func (*Manager[T]) All
func (m *Manager[T]) All() []T

All returns every registered entry in insertion order.

func (*Manager[T]) Each
func (m *Manager[T]) Each(fn func(T))

Each calls fn on every registered entry in insertion order.

func (*Manager[T]) Get
func (m *Manager[T]) Get(name string) (T, bool)

Get returns the entry registered under name and true, or the zero T and false when there is none.

func (*Manager[T]) Has
func (m *Manager[T]) Has(name string) bool

Has reports whether an entry is registered under name.

func (*Manager[T]) Len
func (m *Manager[T]) Len() int

Len returns the number of registered entries.

func (*Manager[T]) MustGet
func (m *Manager[T]) MustGet(name string) T

MustGet returns the entry registered under name. It panics when there is none, so use it only for names the game itself registered.

func (*Manager[T]) Names
func (m *Manager[T]) Names() []string

Names returns the registered names in insertion order.

func (*Manager[T]) Register
func (m *Manager[T]) Register(v T) T

Register adds v to the registry and hands it back. Panics on empty or duplicate name — these are construction-time bugs, not runtime conditions.

It returns what it registered so that a registration can be an expression rather than a statement, which is what lets an entity file be a declaration instead of a procedure.

func (*Manager[T]) Set
func (m *Manager[T]) Set(v T)

Set replaces a registered entry in place, keeping its position in the registration order, and registers the entry when the name is new.

type MouseButton

type MouseButton int

MouseButton identifies which mouse button a widget binds to.

const (
	MouseButtonLeft  MouseButton = iota // the left (primary) button
	MouseButtonRight                    // the right (secondary) button
)

The mouse buttons a widget can bind to.

type Music

type Music struct {
	Name string
	Path string
	Loop bool
}

Music is a track a Scene or a Stage plays while it is showing.

func (Music) GetName
func (m Music) GetName() string

GetName returns the track's Name, its key in the registry.

func (*Music) Source
func (m *Music) Source() string

Source returns the track's Path, which makes a *Music Audible.

func (Music) TypeLabel
func (m Music) TypeLabel() string

TypeLabel returns "music", the kind used in log and panic messages.

type Named

type Named interface {
	GetName() string
}

Named is implemented by every entity that can be registered into a Manager.

type Point

type Point struct {
	X, Y float64
}

Point is a position in screen-space pixels.

func (Point) Add
func (p Point) Add(q Point) Point

Add returns the sum of p and q, p moved by q.

func (Point) Dist
func (p Point) Dist(q Point) float64

Dist returns the straight-line distance between p and q.

type Polygon

type Polygon struct {
	Points []Point
}

Polygon is a closed shape through Points in order; the last point joins back to the first.

func Poly
func Poly(pts ...Point) Polygon

Poly returns the Polygon through pts.

func PolyRect
func PolyRect(x, y, w, h float64) Polygon

PolyRect is the rectangle x,y,w,h as a four-cornered Polygon.

func (Polygon) Bounds
func (g Polygon) Bounds() Rectangle

Bounds returns the smallest Rectangle around every point of g, or the zero Rectangle when g has no points.

func (Polygon) Contains
func (g Polygon) Contains(pt Point) bool

Contains reports whether pt lies inside g, by the even-odd rule. A polygon of fewer than three points contains nothing.

type Rectangle

type Rectangle struct {
	X, Y, W, H float64
}

Rectangle is an axis-aligned box: its top-left corner X, Y and its size W, H, in screen-space pixels.

func Rect
func Rect(x, y, w, h float64) Rectangle

Rect returns the Rectangle with top-left corner x, y and size w, h.

func (Rectangle) Bounds
func (r Rectangle) Bounds() Rectangle

Bounds returns r itself.

func (Rectangle) Contains
func (r Rectangle) Contains(p Point) bool

Contains reports whether p lies in r. The left and top edges belong to the rectangle, the right and bottom ones do not.

type Runner

type Runner interface {
	Tick(ctx *Ctx) Status
}

Runner is one in-flight execution of an Action. Tick advances it one frame and returns whether it's still running, done, or failed.

type SceneLayer

type SceneLayer struct {
	Asset *Asset
	Z     int
}

SceneLayer is one plane of a scene's picture at a depth Z. The cast stands at 0, so negative Z is behind every character and positive Z is in front.

type Script

type Script struct {
	// Name is the script's key in its registry.
	Name string
	// Actions is what the script runs.
	Actions Action
}

Script is a named Action, registered so that a game can start it by name or hand it to the RunScript action (see the action package).

func (Script) GetName
func (s Script) GetName() string

GetName returns the script's Name, its key in the registry.

func (Script) TypeLabel
func (s Script) TypeLabel() string

TypeLabel returns "script", the kind a Script is registered as and the word used in log and panic messages.

type Shape

type Shape interface {
	Contains(p Point) bool
	Bounds() Rectangle
}

Shape is a hotspot area. Rectangle and Polygon both satisfy it.

type Size

type Size struct {
	W, H int
}

Size is a {Width, Height} pair in screen-space pixels.

type Sound

type Sound struct {
	Name string
	Path string
}

Sound is a noise: a door, a latch, a cassette clicking home.

func (Sound) GetName
func (s Sound) GetName() string

GetName returns the sound's Name, its key in the registry.

func (*Sound) Source
func (s *Sound) Source() string

Source returns the sound's Path, which makes a *Sound Audible.

func (Sound) TypeLabel
func (s Sound) TypeLabel() string

TypeLabel returns "sound", the kind used in log and panic messages.

type State

type State struct {
	// contains filtered or unexported fields
}

State is the game's progress: flags, variables, how often each scene was visited and each dialog node talked, and the entities the player has come to know. It is what a save file holds; the zero value is not usable, make one with NewState.

func NewState
func NewState() *State

NewState returns an empty State with all of its maps made.

func (*State) ClearFlag
func (s *State) ClearFlag(name string)

ClearFlag unsets the flag name.

func (*State) Flag
func (s *State) Flag(name string) bool

Flag reports whether the flag name is set.

func (*State) Flags
func (s *State) Flags() map[string]bool

Flags returns a copy of the underlying flag map — for serialization.

func (*State) Known
func (s *State) Known(entity Knowable) int

Known is the order in which the player came to know an entity, counting from 1, or 0 for one they have not.

func (*State) KnownMap
func (s *State) KnownMap() map[string]int

KnownMap returns a copy of the known map — for serialization.

func (*State) LoadFlags
func (s *State) LoadFlags(flags map[string]bool)

LoadFlags replaces the flag map from a saved state.

func (*State) LoadKnown
func (s *State) LoadKnown(known map[string]int)

LoadKnown replaces the known map from a saved state.

func (*State) LoadTalked
func (s *State) LoadTalked(talked map[string]int)

LoadTalked replaces the talked map from a saved state.

func (*State) LoadVars
func (s *State) LoadVars(vars map[string]any)

LoadVars replaces the var map from a saved state.

func (*State) LoadVisited
func (s *State) LoadVisited(visited map[string]int)

LoadVisited replaces the visited map from a saved state.

func (*State) NoteKnown
func (s *State) NoteKnown(entity Knowable)

NoteKnown records that the player now knows entity, giving it the next number in the order State.Known reports. An entity already known keeps its number.

func (*State) NoteTalked
func (s *State) NoteTalked(node string)

NoteTalked counts one more playing of the dialog node.

func (*State) NoteVisit
func (s *State) NoteVisit(name string)

NoteVisit counts one more visit to the scene name.

func (*State) SetFlag
func (s *State) SetFlag(name string)

SetFlag sets the flag name.

func (*State) SetVar
func (s *State) SetVar(name string, v any)

SetVar sets the variable name to v.

func (*State) Talked
func (s *State) Talked(node string) int

Talked returns how many times the dialog node has been played.

func (*State) TalkedMap
func (s *State) TalkedMap() map[string]int

TalkedMap returns a copy of the talked map — for serialization.

func (*State) Var
func (s *State) Var(name string) any

Var returns the variable name, or nil when it was never set.

func (*State) Vars
func (s *State) Vars() map[string]any

Vars returns a copy of the underlying var map — for serialization.

func (*State) Visited
func (s *State) Visited(name string) int

Visited returns how many times the scene name has been entered.

func (*State) VisitedMap
func (s *State) VisitedMap() map[string]int

VisitedMap returns a copy of the visited map — for serialization.

type Status

type Status int

Status is the outcome of one tick of a Runner.

const (
	StatusRunning Status = iota // not finished; tick it again next frame
	StatusDone                  // finished; a sequence moves on
	StatusFailed                // gave up; a sequence stops here
)

The outcomes of a tick.

type Talker

type Talker interface {
	TalkerName() string
}

Talker is whoever a line can be given to — in inkwell a *Character or a *Speaker. Say takes one, and so does a DialogLine, which is what lets a dialog file name the person or the voice itself rather than spell its name.

type Text

type Text []Translation

Text is a string in as many languages as somebody has written it in.

func Format
func Format(format Text, args ...any) Text

Format composes a sentence around other Texts, resolving every part in the same language as the frame it lands in. An argument that is a Text resolves per language; anything else is printed as it stands.

func Plain
func Plain(s string) Text

Plain wraps a string that is not really a translation of anything — a registry key standing in for a label nobody wrote. It answers in every language, because there is nothing about it to translate.

func (Text) Empty
func (t Text) Empty() bool

Empty reports whether the Text carries no translation at all.

func (Text) In
func (t Text) In(lang string) string

In is the Text's wording in one named language, falling back the same way String does.

func (Text) Map
func (t Text) Map(fn func(string) string) Text

Map rewrites every translation, keeping the languages and voices.

func (Text) Resolved
func (t Text) Resolved() Translation

Resolved is the Translation String would read from: the one in Lang, else Fallback, else the first — with its Voice.

func (Text) String
func (t Text) String() string

String resolves the Text against Lang: that language if it is there, then Fallback, then whichever translation was written first.

type Translation

type Translation struct {
	Lang string
	Text string
	// Voice is the recording of this line in this language, if there is one.
	Voice *Voice
}

Translation is one language's wording of one string.

type Voice

type Voice struct {
	Path string
}

Voice is a recorded line. It sits on a Translation, because the English and the Hungarian recording are two files, and Say plays the one the resolved language carries.

func (*Voice) Source
func (v *Voice) Source() string

Source returns the recording's Path, which makes a Voice Audible.

Directories

action Package action holds the generic actions — the ones any Ebitengine game built on inkbase can use — and the combinators every script is built from.
asset Package asset provides the filesystem abstraction, the image cache and the audio player for inkbase games.
chatlog Package chatlog is an inkbase widget: ChatLog, the message log — player commands, in-world replies and system lines — drawn as a box with the newest line at the bottom, older lines scrolling up out of view.
condition Package condition holds the generic conditions: the ones that need nothing but the inkbase.State in the Ctx, or at most a narrow host interface any game can implement.
endcard Package endcard is an inkbase widget: EndCard, a full-screen overlay with the host's end text centred on it, shown whenever that text is not empty.
font Package font provides the built-in glyph atlas and the text drawing and measuring functions for inkbase widgets.
input Package input provides consume-on-use input polling for inkbase hosts and widgets.
keybinding Package keybinding is an inkbase widget: KeyBinding, a key and the action it queues — the whole widget.
letterbox Package letterbox is an inkbase widget: Letterbox, the pair of bars that crop the picture top and bottom while a cutscene plays.
menu Package menu is the menu system: Menu, a nested list in a window — a page of rows, any of which can open a page of its own, as deep as the tree goes.
panel Package panel is an inkbase widget: Panel, a coloured rectangle with an optional border, used as a backdrop for grouping other widgets.
stage Package stage holds Stage: one full-screen thing a game can be showing — a main menu, a settings screen, a splash card, or the world itself.
statusline Package statusline is an inkbase widget: StatusLine, a single line of text that shows the host's flash message while one is up, and the hover hint ("verb + target") otherwise.
textcard Package textcard is an inkbase widget: TextCard, a block of lines centred on the screen — a title card, a credits page that does not roll, an apology.
topbar Package topbar is an inkbase widget: TopBar, a strip across the top of the screen in three sections.
transition Package transition holds the Transition contract and the fade.
widget Package widget is the widget contract: the Widget interface, the Layer constants, and the visibility and ordering helpers a host drives its per-frame loop with.