rl

package
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: 9 Imported by: 3

Documentation

Overview

Package rl provides some facilities for common roguelike programming needs: event queue, field of view and map generation.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Cell

type Cell int

Cell represents a cell in a map Grid, commonly a terrain type or other information associated with a map position.

type CellularAutomataRule

type CellularAutomataRule struct {
	WCutoff1        int  // wall if W(1) >= WCutoff1 (set to 0 to disable)
	WCutoff2        int  // wall if W(2) <= WCutoff2 (set to 25 to disable)
	WallsOutOfRange bool // count out of range positions as walls
	Reps            int  // number of successive iterations of this rule
}

CellularAutomataRule describes the conditions for generating a wall in an iteration of the cellular automata algorithm. In the comments, W(n) is the number of walls in an n-radius area centered at a certain position being processed.

type Event

type Event interface{}

Event represents a message or an action.

type EventQueue

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

EventQueue manages a priority queue of Event elements sorted by their rank in ascending order. The rank may represent for example a turn number or some more fine-grained priority measure.

EventQueue must be created with NewEventQueue.

EventQueue implements gob.Decoder and gob.Encoder for easy serialization.

func NewEventQueue

func NewEventQueue() *EventQueue

NewEventQueue returns a new EventQueue suitable for use.

func (*EventQueue) Empty

func (eq *EventQueue) Empty() bool

Empty reports whether the event queue is empty.

func (*EventQueue) Filter

func (eq *EventQueue) Filter(fn func(ev Event) bool)

Filter removes events that do not satisfy a given predicate from the event queue.

func (*EventQueue) GobDecode

func (eq *EventQueue) GobDecode(bs []byte) error

GobDecode implements gob.GobDecoder.

func (*EventQueue) GobEncode

func (eq *EventQueue) GobEncode() ([]byte, error)

GobEncode implements gob.GobEncoder.

func (*EventQueue) Pop

func (eq *EventQueue) Pop() Event

Pop removes the first element rank-wise (lowest rank) in the event queue and returns it.

func (*EventQueue) PopR added in v0.18.0

func (eq *EventQueue) PopR() (Event, int)

PopR removes the first element rank-wise (lowest rank) in the event queue and returns it, along with its rank.

func (*EventQueue) Push

func (eq *EventQueue) Push(ev Event, rank int)

Push adds a new event to the heap with a given rank. Previously queued events with same rank will be out first.

func (*EventQueue) PushFirst added in v0.18.0

func (eq *EventQueue) PushFirst(ev Event, rank int)

PushFirst adds a new event to the heap with a given rank. It will be out before other events of same rank previously queued.

type FOV

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

FOV represents a field of vision. There are two main algorithms available: VisionMap and SCCVisionMap, and their multiple-source versions. Both algorithms are symmetric (under certain conditions) with expansive walls, and fast.

The VisionMap method algorithm is more permissive and only produces continuous light rays. Moreover, it allows for non-binary visibility (some obstacles may reduce sight range without blocking it completely).

The SCCVisionMap method algorithm is a symmetric shadow casting algorithm based on the one described there:

https://www.albertford.com/shadowcasting/

It offers more euclidean-like geometry, less permissive and with expansive shadows, while still being symmetric and fast enough.

Both algorithms can be combined to obtain a less permissive version of VisionMap with expansive shadows, while keeping the non-binary visibility information.

FOV elements must be created with NewFOV.

FOV implements the gob.Decoder and gob.Encoder interfaces for easy serialization.

func NewFOV

func NewFOV(rg gruid.Range) *FOV

NewFOV returns new ready to use field of view with a given range of valid positions.

func (*FOV) At

func (fov *FOV) At(p gruid.Point) (int, bool)

At returns the total ray cost at a given position from the last source(s) given to VisionMap or LightMap. It returns a false boolean if the position was out of reach.

func (*FOV) From added in v0.18.0

func (fov *FOV) From(lt Lighter, to gruid.Point) (LightNode, bool)

From returns the previous position in the light ray to the given position, as computed in the last VisionMap call. If none, it returns false.

func (*FOV) GobDecode

func (fov *FOV) GobDecode(bs []byte) error

GobDecode implements gob.GobDecoder.

func (*FOV) GobEncode

func (fov *FOV) GobEncode() ([]byte, error)

GobEncode implements gob.GobEncoder.

func (*FOV) Iter

func (fov *FOV) Iter(fn func(LightNode))

Iter iterates a function on the nodes lighted in the last VisionMap or LightMap.

func (*FOV) IterSSC added in v0.18.0

func (fov *FOV) IterSSC(fn func(p gruid.Point))

IterSSC iterates a function on the nodes lighted in the last SCCVisionMap or SCCLightMap.

func (*FOV) LightMap

func (fov *FOV) LightMap(lt Lighter, srcs []gruid.Point) []LightNode

LightMap builds a lighting map with given light sources. It returs a cached slice of lighted nodes. Values can also be consulted with At.

func (*FOV) Range

func (fov *FOV) Range() gruid.Range

Range returns the current FOV's range of positions.

func (*FOV) Ray

func (fov *FOV) Ray(lt Lighter, to gruid.Point) []LightNode

Ray returns a single light ray from the source (viewer) position to another. It should be preceded by a VisionMap call. If the destination position is not within the max distance from the source, a nil slice will be returned.

The returned slice is cached for efficiency, so results will be invalidated by future calls.

func (*FOV) SSCLightMap added in v0.18.0

func (fov *FOV) SSCLightMap(srcs []gruid.Point, maxDepth int, passable func(p gruid.Point) bool, diags bool) []gruid.Point

SSCLightMap is the equivalent of SSCVisionMap with several sources.

func (*FOV) SSCVisionMap added in v0.18.0

func (fov *FOV) SSCVisionMap(src gruid.Point, maxDepth int, passable func(p gruid.Point) bool, diags bool) []gruid.Point

SSCVisionMap implements symmetric shadow casting algorithm based on algorithm described there:

https://www.albertford.com/shadowcasting/

It returns a cached slice of visible points. Visibility of positions can also be checked with the Visible method. Contrary to VisionMap and LightMap, this algorithm can have some discontinuous rays.

func (*FOV) SetRange

func (fov *FOV) SetRange(rg gruid.Range)

SetRange updates the range used by the field of view. If the size is smaller, cached structures will be preserved, otherwise they will be reinitialized.

func (*FOV) Visible added in v0.18.0

func (fov *FOV) Visible(p gruid.Point) bool

Visible returns true if the given position is visible according to the last SCCVisionMap call.

func (*FOV) VisionMap

func (fov *FOV) VisionMap(lt Lighter, src gruid.Point) []LightNode

VisionMap builds a field of vision map for a viewer at src. It returns a cached slice of lighted nodes. Values can also be consulted individually with At.

The algorithm works in a way that can remind of the Dijkstra algorithm, but within each cone between a diagonal and an orthogonal axis (an octant), only movements along those two directions are allowed. This allows the algorithm to be a simple pass on squares around the player, starting from radius 1 until line of sight range.

Going from a gruid.Point p to a gruid.Point q has a cost, which depends essentially on the type of terrain in p, and is determined by a Lighter.

The obtained light rays are lines formed using at most two adjacent directions: a diagonal and an orthogonal one (for example north east and east).

type Grid

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

Grid is modeled after gruid.Grid but with int Cells. It is suitable for representing a map. 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.

Grid implements gob.Decoder and gob.Encoder for easy serialization.

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 the zero value for cells.

func (Grid) At

func (gd Grid) At(p gruid.Point) Cell

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

func (Grid) AtU added in v0.18.0

func (gd Grid) AtU(p gruid.Point) Cell

AtU returns the cell at a given position without checking the grid slice bounds. If the position is out of bounds, it returns a value corresponding to the position in the underlying grid, or the zero value if also out of the underlying grid's range.

It may be somewhat faster than At in tight loops, but most of the time you can get the same performance using GridIterator or iteration functions, which are less error-prone.

func (Grid) Bounds

func (gd Grid) Bounds() gruid.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 gruid.Point) bool

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

func (Grid) Copy

func (gd Grid) Copy(src Grid) gruid.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) Count

func (gd Grid) Count(c Cell) int

Count returns the number of cells which are equal to the given one.

func (Grid) CountFunc

func (gd Grid) CountFunc(fn func(c Cell) bool) int

CountFunc returns the number of cells for which the given function returns true.

func (Grid) Fill

func (gd Grid) Fill(c Cell)

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

func (Grid) FillFunc

func (gd Grid) FillFunc(fn func() Cell)

FillFunc updates the content for all the grid positions in order using the given function return value.

func (*Grid) GobDecode

func (gd *Grid) GobDecode(bs []byte) error

GobDecode implements gob.GobDecoder.

func (*Grid) GobEncode

func (gd *Grid) GobEncode() ([]byte, error)

GobEncode implements gob.GobEncoder.

func (Grid) Iter

func (gd Grid) Iter(fn func(gruid.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(gruid.Point, Cell) Cell)

Map updates the grid content using the given mapping function.

func (Grid) Range

func (gd Grid) Range() gruid.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. It preserves the content, and any new cells get the zero value.

func (Grid) Set

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

Set draws a cell 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() gruid.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 gruid.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.

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.

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() gruid.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. It's faster than calling Set on the grid.

func (*GridIterator) SetP

func (it *GridIterator) SetP(p gruid.Point)

SetP sets the iterator's current position.

type LightNode

type LightNode struct {
	P    gruid.Point // position in the light ray
	Cost int         // light cost
}

LightNode represents the information attached to a given position in a light map.

type Lighter

type Lighter interface {
	// Cost returns the cost of light propagation from a position to
	// an adjacent one given an original source. If you want the resulting
	// FOV to be symmetric, the function should generate symmetric costs
	// for rays in both directions.
	//
	// Note that the FOV algorithm takes care of only providing (from, to)
	// couples that may belong to a same light ray whose source is src,
	// independently of terrain.  This means that the Cost function should
	// essentially take care of terrain considerations, for example giving
	// a cost of 1 if from is a regular ground cell, and a maximal cost if
	// it is a wall, or something in between for fog, bushes or other
	// terrains.
	//
	// As a special case, you normally want Cost(src, src, to) == 1
	// independently of the terrain in src to guarantee symmetry, except
	// for diagonals in certain cases with 4-way movement, because two
	// walls could block vision (for example).
	Cost(src gruid.Point, from gruid.Point, to gruid.Point) int

	// MaxCost indicates the cost limit at which light cannot propagate
	// anymore from the given source. It should normally be equal to
	// maximum sight or light distance.
	MaxCost(src gruid.Point) int
}

Lighter is the interface that captures the requirements for light ray propagation.

type MapGen

type MapGen struct {
	// Rand is the random number generator to be used in map generation.
	Rand *rand.Rand

	// Grid is the destination grid slice where generated maps are drawn.
	Grid Grid
}

MapGen provides some grid-map generation facilities using a given random number generator and a destination grid slice.

func (MapGen) CellularAutomataCave

func (mg MapGen) CellularAutomataCave(wall, ground Cell, winit float64, rules []CellularAutomataRule) int

CellularAutomataCave generates a map using a cellular automata algorithm. You can provide the initial wall filling percentage, and then sets of rules to be applied in a certain number of iterations. The result is not guaranteed to be connected.

The algorithm is based on: http://www.roguebasin.com/index.php?title=Cellular_Automata_Method_for_Generating_Random_Cave-Like_Levels

func (MapGen) KeepCC

func (mg MapGen) KeepCC(pr *paths.PathRange, p gruid.Point, wall Cell) int

KeepCC puts walls in all the positions unreachable from p according to last CCMap or CCMapAll call on pr. Paths are supposed to be bidirectional. It returns the number of cells in the remaining connected component.

func (MapGen) RandomWalkCave

func (mg MapGen) RandomWalkCave(walker RandomWalker, c Cell, fillp float64, walks int) int

RandomWalkCave draws a map in the destination grid using drunk walking. It performs a certain number of approximately equal length random walks, digging using the given cell, until a certain filling percentage (given by a float between 0 and 1) is reached. It returns the number of digged cells. If more than one walk is done, the result is not guaranteed to be connected and has to be made connected later.

func (MapGen) WithGrid

func (mg MapGen) WithGrid(gd Grid) MapGen

WithGrid returns a derived MapGen using the given destination grid slice.

type RandomWalker

type RandomWalker interface {
	// Neighbor produces a random neighbor position.
	Neighbor(gruid.Point) gruid.Point
}

RandomWalker describes the requirements for a random tunnel generator.

type Vault

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

Vault represents a prefabricated room or level section built from a textual description using Parse.

func NewVault added in v0.18.0

func NewVault(s string) (*Vault, error)

NewVault returns a new vault given a contextual representation to be parsed. See Parse method for a specification of valid string format.

func (*Vault) Content

func (v *Vault) Content() string

Content returns the vault's textual content.

func (*Vault) Draw

func (v *Vault) Draw(gd Grid, fn func(rune) Cell) Grid

Draw uses a mapping from runes to cells to draw the vault into a grid. It returns the grid slice that was drawn.

func (*Vault) Iter

func (v *Vault) Iter(fn func(gruid.Point, rune))

Iter iterates a function for all the vault positions and content runes.

func (*Vault) Parse

func (v *Vault) Parse(s string) error

Parse updates the vault's textual content. Each line in the string should have the same length (leading and trailing spaces are removed automatically). Only characters defined by SetRunes are allowed in the textual content.

func (*Vault) Reflect

func (v *Vault) Reflect()

Reflect changes the content with its reflection with respect to a middle vertical axis (order of characters in each line reversed). The result has the same size.

func (*Vault) Rotate

func (v *Vault) Rotate(n int)

Rotate rotates the vault content n times by 90 degrees counter-clockwise (or clockwise for negative n values). The result's size has dimensions exchanged for odd n.

func (*Vault) Runes

func (v *Vault) Runes() string

Runes returns a string containing the currently permitted runes in the textual vault content.

func (*Vault) SetRunes

func (v *Vault) SetRunes(s string)

SetRunes states that the permitted runes in the textual vault content should be among the runes in the given string. If empty, any rune is allowed.

func (*Vault) Size

func (v *Vault) Size() gruid.Point

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

Jump to

Keyboard shortcuts

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