All extensions

@open-rgs/selectors

One primitive serving placement and hold-and-win targeting.

Naming cells

Placement and hold-and-win targeting are the same shape: pick some positions, then act on them. Only the first half varies, so it lives here once.

A selector names cells. Everything else does something to them.
import { all, cols, rows, holding } from "@open-rgs/selectors";

cols([0, 1])(grid, host.rng_next);
holding("WILD")(grid, host.rng_next);

They compose

Set operations rather than options. Adding a rule means combining selectors, not growing a config object.

=
Union, intersect, except, not.
import { except, union, not } from "@open-rgs/selectors";

const target = except(cols([0, 1]), holding("WILD"));

union(cols([0]), holding("SC"));

Random draws are stable

Order is column-major and stable. A selector returning set-iteration order would make a seeded replay diverge between engine versions - a bug that only surfaces in a certification rerun.

randomN draws without replacement and throws rather than under-delivering.
import { randomN, upTo, oneOf } from "@open-rgs/selectors";

randomN(3, target);
upTo(3, target);
oneOf(target);