# `Cauldron2D.Rng`
[🔗](https://github.com/jaman/cauldron/blob/v0.1.3/cauldron_2d/lib/cauldron_2d/rng.ex#L1)

A random number generator carried in a game's state rather than the process dictionary.

Every function here takes a generator and returns `{value, next_generator}`. A caller must
thread the returned generator into the following call; reusing an earlier one repeats its
values. Given the same seed and the same sequence of calls, a run replays exactly.

Wraps `:rand`'s stateful API on the `:exsss` algorithm.

    rng = Cauldron2D.Rng.new(1234)
    {damage, rng} = Cauldron2D.Rng.dice(rng, 2, 6)
    {critical?, _rng} = Cauldron2D.Rng.chance(rng, 1, 20)

# `t`

```elixir
@type t() :: :rand.state()
```

# `between`

```elixir
@spec between(t(), integer(), integer()) :: {integer(), t()}
```

An integer in `lo..hi`, inclusive, uniformly. `hi` must not be less than `lo`.

# `chance`

```elixir
@spec chance(t(), pos_integer(), pos_integer()) :: {boolean(), t()}
```

True with probability `numerator / denominator`. Both must be positive integers.

# `dice`

```elixir
@spec dice(t(), pos_integer(), pos_integer()) :: {pos_integer(), t()}
```

The sum of `count` independent rolls of a die with `sides` faces.

# `new`

```elixir
@spec new(integer()) :: t()
```

A generator seeded from `seed`, which may be any integer.

# `pick`

```elixir
@spec pick(t(), [term()]) :: {term() | nil, t()}
```

One element of `list`, each equally likely, or `nil` when `list` is empty.

# `random`

```elixir
@spec random() :: {t(), integer()}
```

A generator seeded from the system clock, and the seed it used.

Keep the returned seed to replay the same run through `new/1`.

# `roll`

```elixir
@spec roll(t(), pos_integer()) :: {pos_integer(), t()}
```

An integer in `1..n`, uniformly. `n` must be at least 1.

# `shuffle`

```elixir
@spec shuffle(t(), [term()]) :: {[term()], t()}
```

The elements of `list` in a random order.

A Fisher-Yates shuffle, so every ordering is equally likely however long the list is. Costs
one roll per element.

# `weighted`

```elixir
@spec weighted(t(), [{non_neg_integer(), term()}]) :: {term() | nil, t()}
```

One value from a list of `{weight, value}` pairs, chosen in proportion to the weights.

Weights are relative and need not sum to anything in particular. Each must be a non-negative
integer, and at least one must be positive; a weight of `0` is a value that is never chosen.
Returns `nil` for an empty list.

Raises `ArgumentError` on a weight that is not a non-negative integer, and on a list whose
weights are all zero — a list that cannot answer, rather than one that answers oddly.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
