gruid

package module
v0.22.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 23, 2022 License: ISC Imports: 11 Imported by: 11

README

Gruid

pkg.go.dev godocs.io

The gruid module provides packages for easily building grid-based applications in Go. The library abstracts rendering and input for different platforms. There are drivers available for terminal apps (gruid-tcell), native graphical apps (gruid-sdl) and browser apps (gruid-js). The original application for the library was creating grid-based games, but it's also well-suited for any grid-based application.

The core gruid package uses a convenient and flexible architecture of updating a model in response to messages strongly inspired from the bubbletea module for building terminal apps, which in turn is based on the functional Elm Architecture. The architecture has been adapted to be more idiomatic in Go in the context of grid-based applications: less functional and more efficient.

You can find examples below in the Examples section.

Overview of packages

The full documentation is linked at the top of this README. We provide here a quick overview.

The gruid package defines the Model and Driver interfaces and allows to start the “update on message then draw” main loop of an application. It also defines a convenient and efficient slice grid structure to represent the logical contents of the screen and manipulate them.

The ui package defines common UI widgets and utilities: menu/table widget, pager, text input, label, styled text drawing facilities and replay functionality.

The tiles package contains helpers for drawing fonts on images, which can be used to manage character tiles using a Driver from either gruid-sdl or gruid-js.

The paths package provides efficient implementations of some common pathfinding algorithms that are often used in grid-based games, such as roguelikes. You will find implementations of the A* and JPS algorithms, as well as Dijkstra, breadth first, and connected components maps computations. See move.go in the movement example in gruid-examples for an annotated example using JPS and the mouse.

The rl package provides some additional utilities commonly needed in grid-based games such as roguelikes. The package provides an event priority queue, two complementary field of view algorithms, map generation algorithms, as well as vault parsing and manipulation utilities.

Drivers

The tcell, sdl, and js packages in the (gruid-tcell), (gruid-sdl) and (gruid-js) modules provide specific rendering and input implementations satisfying gruid's package Driver interface. The provided terminal driver only handles full-window applications. See the README.md files in the respective repositories for specific build and deployment instructions (gruid-sdl will require SDL2, and gruid-js will require a bit of HTML and js).

Examples

The gruid-examples module offers some simple annotated examples of gruid usage.

You may want to look also into some real world examples of gruid programs:

See also

If you need to handle wide-characters, that is characters that take two cells in the terminal, you may want to look into go-runewidth.

The clipboard module may be of interest for some applications too, as copying and pasting is not handled by gruid. Note that, at this time, the clipboard module does not support the js platform, but there's at least one fork that does.

As gruid only provides a few map generation algorithms, you may be interested in the dngn module, which provides map generation algorithms too, though its representation of maps is different.

Documentation

Overview

Package gruid provides a model for building grid-based applications. The interface abstracts rendering and input for different platforms. There are drivers for terminal apps (gruid-tcell), native graphical apps (gruid-sdl) and browser apps (gruid-js).

The package uses an architecture of updating a model in response to messages strongly inspired from the bubbletea module for building terminal apps (https://github.com/charmbracelet/bubbletea), which in turn is based on the Elm Architecture (https://guide.elm-lang.org/architecture/).

The typical usage looks like this:

// model implements gruid.Model interface and represents the
// application's state.
type model struct {
	grid gruid.Grid // user interface grid
	// other fields with the state of the application
}

func (m *model) Update(msg gruid.Msg) gruid.Effect {
	// Update your application's state in response to messages.
}

func (m *model) Draw() gruid.Grid {
	// Write your rendering into the grid and return it.
}

func main() {
	gd := gruid.NewGrid(80, 24)
	m := &model{grid: gd, ...}
	// Specify a driver among the provided ones.
	driver := tcell.NewDriver(...)
	app := gruid.NewApp(gruid.AppConfig{
		Driver: driver,
		Model: m,
	})
	// Start the main loop of the application.
	if err := app.Start(context.Background()); err != nil {
		log.Fatal(err)
	}
}

The values of type gruid.Effect returned by Update are optional and represent concurrently executed functions that produce messages. The gruid.Grid type is a convenient 2-dimensional slice type representing the screen's logical contents. See the relevant types documentation for details and usage.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type App

type App struct {
	// CatchPanics ensures that Close is called on the driver before ending
	// the Start loop. When a panic occurs, it will be recovered, the stack
	// trace will be printed and an error will be returned. It defaults to
	// true.
	CatchPanics bool
	// contains filtered or unexported fields
}

App represents a message and model-driven application with a grid-based user interface.

func NewApp

func NewApp(cfg AppConfig) *App

NewApp creates a new App with the given configuration options.

func (*App) Start

func (app *App) Start(ctx context.Context) (err error)

Start initializes the application and runs its main loop. The context argument can be used as a means to prematurely cancel the loop. You can usually use an empty context here.

type AppConfig

type AppConfig struct {
	Model  Model  // application state
	Driver Driver // input and rendering driver

	// FrameWriter is an optional io.Writer for recording frames. They can
	// be decoded after a successful Start session with a FrameDecoder. If
	// nil, no frame recording will be done. It is your responsibility to
	// call Close on the Writer after Start returns.
	FrameWriter io.Writer

	// Logger is optional and is used to log non-fatal IO errors.
	Logger *log.Logger
}

AppConfig contains the configuration options for creating a new App.

type AttrMask

type AttrMask uint32

AttrMask can be used to add custom styling information. It can for example be used to map to specific terminal attributes (with GetStyle), or use special images (with GetImage), when appropriate.

It may be used as a bitmask, like terminal attributes, or as a generic value for constants.

const AttrsDefault AttrMask = 0

AttrsDefault represents the default styling attributes.

type Cell

type Cell struct {
	Rune  rune  // cell content character
	Style Style // cell style
}

Cell contains all the content and styling information to represent a cell in the grid.

func (Cell) WithRune

func (c Cell) WithRune(r rune) Cell

WithRune returns a derived Cell with a new Rune.

func (Cell) WithStyle

func (c Cell) WithStyle(st Style) Cell

WithStyle returns a derived Cell with a new Style.

type Cmd

type Cmd func() Msg

Cmd is an Effect that returns a message. Commands returned by Update are executed on their own goroutine. You can use them for things like single event timers and short-lived IO operations with a single result. A nil command is discarded and does nothing.

Cmd implements the Effect interface.

func End

func End() Cmd

End returns a special command that signals the application to end its Start loop. Note that the application does not wait for pending effects to complete before exiting the Start loop, so you may have to wait for any of those commands messages before using End.

type Color

type Color uint32

Color is a generic value for representing colors. Those have to be mapped to concrete foreground and background colors for each driver, as appropriate.

const ColorDefault Color = 0

ColorDefault should get special treatment by drivers and be mapped, when it makes sense, to a default color, both for foreground and background.

type Driver

type Driver interface {
	// Init initializes the driver, so that you can then call its other
	// methods.
	Init() error

	// PollMsgs is a subscription for input messages. It returns an error
	// in case the driver input loop suffered a non recoverable error. It
	// should handle cancellation of the passed context and return as
	// appropriate.
	PollMsgs(context.Context, chan<- Msg) error

	// Flush sends grid's last frame changes to the driver.
	Flush(Frame)

	// Close may execute needed code to finalize the screen and release
	// resources. Redundant Close() calls are ignored. After Close() it is
	// possible to call Init() again.
	Close()
}

Driver handles both user input and rendering. When creating an App and using the Start main loop, you will not have to call those methods directly. You may reuse the same driver for another application after the current application's Start loop ends.

type DriverPollMsg added in v0.21.0

type DriverPollMsg interface {
	// The PollMsg returns an input message if any, in a non-blocking way.
	// If no message can be retrieved, nil should be returned. If a non
	// recoverable input error happens, an error can be returned.
	PollMsg() (Msg, error)
}

DriverPollMsg is an optional interface that can be satisfied by drivers. Such drivers will be run such that the message polling is executed in the same thread as main using a non-blocking polling message method, instead of PollMsgs. This may be necessary with drivers whose input system is not thread safe.

type Effect

type Effect interface {
	// contains filtered or unexported methods
}

Effect is an interface type for representing either command or subscription functions. Those functions generally represent IO operations, either producing a single message or several. They are executed on their own goroutine after being returned by the Update method of the model. A nil effect is discarded and does nothing.

The types Cmd and Sub implement the Effect interface. See their respective documentation for specific usage details.

func Batch

func Batch(effs ...Effect) Effect

Batch peforms a bunch of effects concurrently with no ordering guarantees about the potential results.

type Frame

type Frame struct {
	Time   time.Time   // time of frame drawing: used for replay
	Cells  []FrameCell // cells that changed from previous frame
	Width  int         // width of the whole grid when the frame was issued
	Height int         // height of the whole grid when the frame was issued
}

Frame contains the necessary information to draw the frame changes from a frame to the next. One is sent to the driver after every Draw.

type FrameCell

type FrameCell struct {
	Cell Cell  // cell content and styling
	P    Point // absolute position in the whole grid
}

FrameCell represents a cell drawing instruction at a specific absolute position in the whole grid.

type FrameDecoder

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

FrameDecoder manages the decoding of the frame recording stream produced by the running of an application, in case a FrameWriter was provided. It can be used to replay an application session.

func NewFrameDecoder

func NewFrameDecoder(r io.Reader) (*FrameDecoder, error)

NewFrameDecoder returns a FrameDecoder using a given reader as source for frames.

It is your responsibility to call Close on the reader when done.

func (*FrameDecoder) Decode

func (fd *FrameDecoder) Decode(framep *Frame) error

Decode retrieves the next frame from the input stream. The frame pointer should be non nil. If the input is at EOF, it returns the error io.EOF.

type Grid

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

Grid represents the grid that is used to draw a model logical contents that are then sent to the driver. It is a slice type, so it represents a rectangular range within an underlying original grid. Due to how it is represented internally, it is more efficient to iterate whole lines first, as in the following pattern:

max := gd.Size()
for y := 0; y < max.Y; y++ {
	for x := 0; x < max.X; x++ {
		p := Point{X: x, Y: y}
		// do something with p and the grid gd
	}
}

Most iterations can be performed using the Slice, Fill, Copy, Map and Iter methods. An alternative choice is to use the Iterator method.

Grid elements must be created with NewGrid.

Example
package main

import (
	"fmt"

	"github.com/anaseto/gruid"
)

func main() {
	// Create a new 20x20 grid.
	gd := gruid.NewGrid(20, 20)
	// Fill the whole grid with dots.
	gd.Fill(gruid.Cell{Rune: '.'})
	// Define a range (5,5)-(15,15).
	rg := gruid.NewRange(5, 5, 15, 15)
	// Define a slice of the grid using the range.
	rectangle := gd.Slice(rg)
	// Fill the rectangle with #.
	rectangle.Fill(gruid.Cell{Rune: '#'})
	// Print the grid using a non-styled string representation.
	fmt.Print(gd)
}
Output:

....................
....................
....................
....................
....................
.....##########.....
.....##########.....
.....##########.....
.....##########.....
.....##########.....
.....##########.....
.....##########.....
.....##########.....
.....##########.....
.....##########.....
....................
....................
....................
....................
....................

func NewGrid

func NewGrid(w, h int) Grid

NewGrid returns a new grid with given width and height in cells. The width and height should be positive or null. The new grid contains all positions (X,Y) with 0 <= X < w and 0 <= Y < h. The grid is filled with Cell{Rune: ' '}.

func (Grid) At

func (gd Grid) At(p Point) Cell

At returns the cell content and styling at a given position. If the position is out of range, it returns the zero value.

func (Grid) Bounds

func (gd Grid) Bounds() Range

Bounds returns the range that is covered by this grid slice within the underlying original grid.

func (Grid) Contains

func (gd Grid) Contains(p Point) bool

Contains returns true if the given relative position is within the grid.

func (Grid) Copy

func (gd Grid) Copy(src Grid) Point

Copy copies elements from a source grid src into the destination grid gd, and returns the copied grid-slice size, which is the minimum of both grids for each dimension. The result is independent of whether the two grids referenced memory overlaps or not.

func (Grid) Fill

func (gd Grid) Fill(c Cell)

Fill sets the given cell as content for all the grid positions.

func (Grid) Iter

func (gd Grid) Iter(fn func(Point, Cell))

Iter iterates a function on all the grid positions and cells.

func (Grid) Iterator

func (gd Grid) Iterator() GridIterator

Iterator returns an iterator that can be used to iterate on the grid. It may be convenient when more flexibility than the provided by the other iteration functions is needed. It is used as follows:

it := gd.Iterator()
for it.Next() {
	// call it.P() or it.Cell() or it.SetCell() as appropriate
}

func (Grid) Map

func (gd Grid) Map(fn func(Point, Cell) Cell)

Map updates the grid content using the given mapping function.

func (Grid) Range

func (gd Grid) Range() Range

Range returns the range with Min set to (0,0) and Max set to gd.Size(). It may be convenient when using Slice with a range Shift.

func (Grid) Resize

func (gd Grid) Resize(w, h int) Grid

Resize is similar to Slice, but it only specifies new dimensions, and if the range goes beyond the underlying original grid range, it will grow the underlying grid. In case of growth, it preserves the content, and new cells are initialized to Cell{Rune: ' '}.

func (Grid) Set

func (gd Grid) Set(p Point, c Cell)

Set draws cell content and styling at a given position in the grid. If the position is out of range, the function does nothing.

func (Grid) Size

func (gd Grid) Size() Point

Size returns the grid (width, height) in cells, and is a shorthand for gd.Range().Size().

func (Grid) Slice

func (gd Grid) Slice(rg Range) Grid

Slice returns a rectangular slice of the grid given by a range relative to the grid. If the range is out of bounds of the parent grid, it will be reduced to fit to the available space. The returned grid shares memory with the parent.

This makes it easy to use relative coordinates when working with UI elements.

func (Grid) String added in v0.12.0

func (gd Grid) String() string

String returns a simplified string representation of the grid's runes, without the styling.

type GridIterator

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

GridIterator represents a stateful iterator for a grid. They are created with the Iterator method.

Example
package main

import (
	"fmt"

	"github.com/anaseto/gruid"
)

func main() {
	// Create a new 26x2 grid.
	gd := gruid.NewGrid(26, 2)
	// Get an iterator.
	it := gd.Iterator()
	// Iterate on the grid and fill it with successive alphabetic
	// characters.
	r := 'a'
	max := gd.Size()
	for it.Next() {
		it.SetCell(gruid.Cell{Rune: r})
		r++
		if it.P().X == max.X-1 {
			r = 'A'
		}
	}
	// Print the grid using a non-styled string representation.
	fmt.Print(gd)
}
Output:

abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ

func (*GridIterator) Cell

func (it *GridIterator) Cell() Cell

Cell returns the Cell in the grid at the iterator's current position.

func (*GridIterator) Next

func (it *GridIterator) Next() bool

Next advances the iterator the next position in the grid.

func (*GridIterator) P

func (it *GridIterator) P() Point

P returns the iterator's current position.

func (*GridIterator) Reset

func (it *GridIterator) Reset()

Reset resets the iterator's state so that it can be used again.

func (*GridIterator) SetCell

func (it *GridIterator) SetCell(c Cell)

SetCell updates the grid cell at the iterator's current position.

func (*GridIterator) SetP

func (it *GridIterator) SetP(p Point)

SetP sets the iterator's current position.

type Key

type Key string

Key represents the name of a key press.

const (
	KeyArrowDown  Key = "ArrowDown"  // can be KP_2
	KeyArrowLeft  Key = "ArrowLeft"  // can be KP_4
	KeyArrowRight Key = "ArrowRight" // can be KP_6
	KeyArrowUp    Key = "ArrowUp"    // can be KP_8
	KeyBackspace  Key = "Backspace"
	KeyDelete     Key = "Delete"
	KeyEnd        Key = "End"   // can be KP_1
	KeyEnter      Key = "Enter" // can be KP_5 (arbitrary choice)
	KeyEscape     Key = "Escape"
	KeyHome       Key = "Home" // can be KP_7
	KeyInsert     Key = "Insert"
	KeyPageDown   Key = "PageDown" // can be KP_3
	KeyPageUp     Key = "PageUp"   // can be KP_9
	KeySpace      Key = " "        // constant for clarity (single character)
	KeyTab        Key = "Tab"
)

This is the list of the supported non single-character named keys. The drivers that support keypad with numlock off may report some KP_* keypad keys as one of this list, as specified in the comments.

func (Key) In

func (k Key) In(keys []Key) bool

In reports whether the key is found among a given list of keys.

func (Key) IsRune

func (k Key) IsRune() bool

IsRune reports whether the key is a single-rune string and not a named key.

type ModMask

type ModMask int16

ModMask is a bit mask of modifier keys.

const (
	ModShift ModMask = 1 << iota
	ModCtrl
	ModAlt
	ModMeta
	ModNone ModMask = 0
)

These values represent modifier keys for a MsgKeyDown message. Those are not supported equally well across all platforms and drivers, for both technical and simplicity reasons. In particular, terminal drivers may not report shift for key presses corresponding to upper case letters. Modifiers may conflict in some cases with browser or system shortcuts too. If you want portability across platforms and drivers, your application should not depend on them for its core functionality.

func (ModMask) String

func (m ModMask) String() string

type Model

type Model interface {
	// Update is called when a message is received. Use it to update your
	// model in response to messages and/or send commands or subscriptions.
	// It is always called the first time with a MsgInit message.
	Update(Msg) Effect

	// Draw is called after every Update. Use this function to draw the UI
	// elements in a grid to be returned. If only parts of the grid are to
	// be updated, you can return a smaller grid slice, or an empty grid
	// slice to skip any drawing work. Note that the contents of the grid
	// slice are then compared to the previous state at the same bounds,
	// and only the changes are sent to the driver anyway.
	Draw() Grid
}

Model contains the application's state.

type MouseAction

type MouseAction int

MouseAction represents mouse buttons.

const (
	MouseMain      MouseAction = iota // left button
	MouseAuxiliary                    // middle button
	MouseSecondary                    // right button
	MouseWheelUp                      // wheel impulse up
	MouseWheelDown                    // wheel impulse down
	MouseRelease                      // button release
	MouseMove                         // mouse motion
)

This is the list of supported mouse buttons and actions. It is intentionally short for simplicity and best portability across drivers. Pressing several mouse buttons simultaneously is not reported and, in those cases, only one release event will be sent.

func (MouseAction) String

func (ma MouseAction) String() string

type Msg

type Msg interface{}

Msg represents an action and triggers the Update function of the model. Note that nil messages are discarded and do not trigger Update.

type MsgInit

type MsgInit struct{}

MsgInit is a special message that is always sent first to Update after calling Start on the application.

type MsgKeyDown

type MsgKeyDown struct {
	Key Key // name of the key in MsgKeyDown event

	// Mod represents modifier keys. They are not portable across
	// different platforms and drivers. Avoid using them for core
	// functionality in portable applications.
	Mod ModMask

	Time time.Time // time when the event was generated
}

MsgKeyDown represents a key press.

type MsgMouse

type MsgMouse struct {
	Action MouseAction // mouse action (click, release, move)
	P      Point       // mouse position in the grid
	Mod    ModMask     // modifier keys (unequal driver support)
	Time   time.Time   // time when the event was generated
}

MsgMouse represents a mouse user input event.

type MsgQuit

type MsgQuit time.Time

MsgQuit may be reported by some drivers to request termination of the application, such as when the main window is closed. It reports the time at which the driver's request was received.

type MsgScreen

type MsgScreen struct {
	Width  int       // screen width in cells
	Height int       // screen height in cells
	Time   time.Time // time when the event was generated
}

MsgScreen is reported by some drivers when the screen has been exposed in some way and a complete redraw is necessary. It may happen for example after a resize, or after a change of tile set invalidating current displayed content. Note that the application takes care of the redraw, so you may not need to handle it in most cases, unless you want to adapt grid size and layout in response to a potential screen resize.

type Point

type Point struct {
	X int
	Y int
}

Point represents an (X,Y) position in a grid. It follows conventions similar to the ones used by the standard library image.Point.

func (Point) Add

func (p Point) Add(q Point) Point

Add returns vector p+q.

func (Point) Div

func (p Point) Div(k int) Point

Div returns the vector p/k.

func (Point) In

func (p Point) In(rg Range) bool

In reports whether the position is within the given range.

func (Point) Mul

func (p Point) Mul(k int) Point

Mul returns the vector p*k.

func (Point) Shift

func (p Point) Shift(x, y int) Point

Shift returns a new point with coordinates shifted by (x,y). It's a shorthand for p.Add(Point{x,y}).

func (Point) String added in v0.12.0

func (p Point) String() string

String returns a string representation of the form "(x,y)".

func (Point) Sub

func (p Point) Sub(q Point) Point

Sub returns vector p-q.

type Range

type Range struct {
	Min, Max Point
}

Range represents a rectangle in a grid that contains all the positions P such that Min <= P < Max coordinate-wise. A range is well-formed if Min <= Max. When non-empty, Min represents the upper-left position in the range, and Max-(1,1) the lower-right one.

func NewRange

func NewRange(x0, y0, x1, y1 int) Range

NewRange returns a new Range with coordinates (x0, y0) for Min and (x1, y1) for Max. The returned range will have minimum and maximum coordinates swapped if necessary, so that the range is well-formed.

func (Range) Add

func (rg Range) Add(p Point) Range

Add returns a range of same size translated by +p.

func (Range) Column

func (rg Range) Column(x int) Range

Column reduces the range to relative column x, or an empty range if out of bounds.

func (Range) Columns

func (rg Range) Columns(x0, x1 int) Range

Columns reduces the range to relative columns between x0 (included) and x1 (excluded), or an empty range if out of bounds.

func (Range) Empty

func (rg Range) Empty() bool

Empty reports whether the range contains no positions.

func (Range) Eq

func (rg Range) Eq(r Range) bool

Eq reports whether the two ranges containt the same set of points. All empty ranges are considered equal.

func (Range) In

func (rg Range) In(r Range) bool

In reports whether range rg is completely contained in range r.

func (Range) Intersect

func (rg Range) Intersect(r Range) Range

Intersect returns the largest range contained both by rg and r. If the two ranges do not overlap, the zero range will be returned.

func (Range) Iter

func (rg Range) Iter(fn func(Point))

Iter calls a given function for all the positions of the range.

func (Range) Line

func (rg Range) Line(y int) Range

Line reduces the range to relative line y, or an empty range if out of bounds.

func (Range) Lines

func (rg Range) Lines(y0, y1 int) Range

Lines reduces the range to relative lines between y0 (included) and y1 (excluded), or an empty range if out of bounds.

func (Range) Overlaps

func (rg Range) Overlaps(r Range) bool

Overlaps reports whether the two ranges have a non-zero intersection.

func (Range) RelMsg

func (rg Range) RelMsg(msg Msg) Msg

RelMsg returns a range-relative version of messages defined by the gruid package. Currently, it only affects mouse messages, which are given positions relative to the range.

func (Range) Shift

func (rg Range) Shift(x0, y0, x1, y1 int) Range

Shift returns a new range with coordinates shifted by (x0,y0) and (x1,y1).

func (Range) Size

func (rg Range) Size() Point

Size returns the (width, height) of the range in cells.

func (Range) String added in v0.12.0

func (rg Range) String() string

String returns a string representation of the form "(x0,y0)-(x1,y1)".

func (Range) Sub

func (rg Range) Sub(p Point) Range

Sub returns a range of same size translated by -p.

func (Range) Union

func (rg Range) Union(r Range) Range

Union returns the smallest range containing both rg and r.

type Style

type Style struct {
	Fg    Color    // foreground color
	Bg    Color    // background color
	Attrs AttrMask // custom styling attributes
}

Style represents the styling information of a cell: foreground color, background color and custom attributes.

func (Style) WithAttrs

func (st Style) WithAttrs(attrs AttrMask) Style

WithAttrs returns a derived style with new attributes.

func (Style) WithBg

func (st Style) WithBg(cl Color) Style

WithBg returns a derived style with a new background color.

func (Style) WithFg

func (st Style) WithFg(cl Color) Style

WithFg returns a derived style with a new foreground color.

type Sub

type Sub func(context.Context, chan<- Msg)

Sub is similar to Cmd, but instead of returning a message, it sends messages to a channel. Subscriptions should only be used for long running functions where more than one message will be produced, for example to send messages delivered by a time.Ticker, or to report messages from listening on a socket. The function should handle the context and terminate as appropriate.

Sub implements the Effect interface.

Directories

Path Synopsis
Package paths provides utilities for efficient pathfinding in rectangular maps.
Package paths provides utilities for efficient pathfinding in rectangular maps.
Package rl provides some facilities for common roguelike programming needs: event queue, field of view and map generation.
Package rl provides some facilities for common roguelike programming needs: event queue, field of view and map generation.
Package tiles provides common utilities for manipulation of graphical tiles, such as drawing fonts.
Package tiles provides common utilities for manipulation of graphical tiles, such as drawing fonts.
Package ui defines common UI utilities for gruid: menu/table widget, pager, text input, label, text drawing facilities and replay functionality.
Package ui defines common UI utilities for gruid: menu/table widget, pager, text input, label, text drawing facilities and replay functionality.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL