# rng

`import "github.com/matjam/bunyip/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.

## Functions

<a id="WeightedIndex"></a>

### WeightedIndex

```go
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

<a id="Rand"></a>

### Rand

```go
type Rand struct {
	// contains filtered or unexported fields
}
```

Rand is one PCG32 stream. It also satisfies math/rand/v2's Source.

<a id="New"></a>

#### New

```go
func New(seed uint64) *Rand
```

New seeds a generator.

Example:

```go
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)
}
```

Output:

```
44 23 95
true
```

<a id="NewStream"></a>

#### NewStream

```go
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.

<a id="Rand.Between"></a>

#### Rand.Between

```go
func (r *Rand) Between(lo, hi float32) float32
```

Between returns a value in \[lo, hi).

<a id="Rand.Chance"></a>

#### Rand.Chance

```go
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.

<a id="Rand.Float"></a>

#### Rand.Float

```go
func (r *Rand) Float() float32
```

Float returns a value in \[0, 1).

<a id="Rand.Float64"></a>

#### Rand.Float64

```go
func (r *Rand) Float64() float64
```

Float64 returns a value in \[0, 1).

<a id="Rand.Fork"></a>

#### Rand.Fork

```go
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:

```go
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))
}
```

Output:

```
true
```

<a id="Rand.Intn"></a>

#### Rand.Intn

```go
func (r *Rand) Intn(n int) int
```

Intn returns a value in \[0, n). It panics when n is not positive.

<a id="Rand.Normal"></a>

#### Rand.Normal

```go
func (r *Rand) Normal(mean, stddev float32) float32
```

Normal returns a normally distributed value (Box-Muller).

<a id="Rand.Pick"></a>

#### Rand.Pick

```go
func (r *Rand) Pick[T any](items []T) T
```

Pick returns a random element; it panics on an empty slice.

Example:

```go
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))
}
```

Output:

```
potion
3
```

<a id="Rand.Range"></a>

#### Rand.Range

```go
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.

<a id="Rand.Restore"></a>

#### Rand.Restore

```go
func (r *Rand) Restore(state, inc uint64)
```

Restore sets the state returned by State.

<a id="Rand.Roll"></a>

#### Rand.Roll

```go
func (r *Rand) Roll(dice, sides int) int
```

Roll sums dice of the given sides, as in Roll(2, 6) for 2d6.

<a id="Rand.Shuffle"></a>

#### Rand.Shuffle

```go
func (r *Rand) Shuffle[T any](items []T)
```

Shuffle permutes the slice in place (Fisher-Yates).

<a id="Rand.State"></a>

#### Rand.State

```go
func (r *Rand) State() (state, inc uint64)
```

State returns the generator's full state for saving.

<a id="Rand.Uint32"></a>

#### Rand.Uint32

```go
func (r *Rand) Uint32() uint32
```

Uint32 returns the next 32 random bits.

<a id="Rand.Uint64"></a>

#### Rand.Uint64

```go
func (r *Rand) Uint64() uint64
```

Uint64 returns the next 64 random bits.
