Package github.com/matjam/bunyip/rng
rng
Package rng provides a small, fast, seedable random number generator (PCG32) for games. The same seed always gives the same sequence on every platform, streams can be forked so systems do not disturb each other, and the state can be saved and restored.
To make a source, call New with a seed. Fork derives an independent stream from it, so a dungeon generator, loot tables and particle jitter each take their own, and adding a call to one never changes what another produces, which keeps seeds shareable and replays exact. Besides the integer and float draws there are game helpers: Roll for dice (Roll(2, 6) is 2d6), Chance, Range and Between, Pick, WeightedIndex, Shuffle and Normal. State and Restore put the generator into a save file. Sources are not safe for concurrent use; fork one per goroutine.
Index
func WeightedIndex(r *Rand, weights []float32) int- type Rand
func New(seed uint64) *Randfunc NewStream(seed, stream uint64) *Randfunc (r *Rand) Between(lo, hi float32) float32func (r *Rand) Chance(p float32) boolfunc (r *Rand) Float() float32func (r *Rand) Float64() float64func (r *Rand) Fork() *Randfunc (r *Rand) Intn(n int) intfunc (r *Rand) Normal(mean, stddev float32) float32func (r *Rand) Pick[T any](items []T) Tfunc (r *Rand) Range(lo, hi int) intfunc (r *Rand) Restore(state, inc uint64)func (r *Rand) Roll(dice, sides int) intfunc (r *Rand) Shuffle[T any](items []T)func (r *Rand) State() (state, inc uint64)func (r *Rand) Uint32() uint32func (r *Rand) Uint64() uint64
Functions
WeightedIndex source
func WeightedIndex(r *Rand, weights []float32) int
WeightedIndex picks an index with probability proportional to its weight; weights at or below zero are never chosen. It returns -1 when nothing can be picked. Weights and their positive sum must be finite.
Types
type Rand source
type Rand struct {
// contains filtered or unexported fields
}
Rand is one PCG32 stream. It also satisfies math/rand/v2's Source.
New source
func New(seed uint64) *Rand
New seeds a generator.
Example
package main
import (
"fmt"
"github.com/matjam/bunyip/rng"
)
func main() {
// The same seed gives the same sequence on every platform.
r := rng.New(42)
fmt.Println(r.Intn(100), r.Intn(100), r.Intn(100))
fmt.Println(r.Roll(2, 6) >= 2)
}
44 23 95
true
NewStream source
func NewStream(seed, stream uint64) *Rand
NewStream seeds a generator on a particular stream. Only the low 63 bits of stream select the sequence; stream values differing solely in the highest bit select the same sequence.
Chance source
func (r *Rand) Chance(p float32) bool
Chance reports true with probability p: p <= 0 is always false and p >= 1 is always true. Every call advances the generator.
Fork source
func (r *Rand) Fork() *Rand
Fork derives an independent generator from this one's next values,
so a subsystem can take its own stream without disturbing the parent's
sequence any further.
Example
package main
import (
"fmt"
"github.com/matjam/bunyip/rng"
)
func main() {
// Forked streams let one system roll dice without disturbing another.
world := rng.New(1)
combat := world.Fork()
a := combat.Intn(1000)
combat2 := rng.New(1).Fork()
fmt.Println(a == combat2.Intn(1000))
}
true
Intn source
func (r *Rand) Intn(n int) int
Intn returns a value in [0, n). It panics when n is not positive.
Normal source
func (r *Rand) Normal(mean, stddev float32) float32
Normal returns a normally distributed value (Box-Muller).
Pick source
func (r *Rand) Pick[T any](items []T) T
Pick returns a random element; it panics on an empty slice.
Example
package main
import (
"fmt"
"github.com/matjam/bunyip/rng"
)
func main() {
r := rng.New(7)
loot := []string{"sword", "shield", "potion"}
fmt.Println(r.Pick(loot))
r.Shuffle(loot)
fmt.Println(len(loot))
}
potion
3
Range source
func (r *Rand) Range(lo, hi int) int
Range returns a value in [lo, hi], inclusive at both ends, swapping reversed bounds. The inclusive range width must fit in a positive int.
Roll source
func (r *Rand) Roll(dice, sides int) int
Roll sums dice of the given sides, as in Roll(2, 6) for 2d6.
Shuffle source
func (r *Rand) Shuffle[T any](items []T)
Shuffle permutes the slice in place (Fisher-Yates).