@typeonce/ritmo-math 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +183 -0
  2. package/README.md +14 -4
  3. package/dist/Collide2.d.ts +2 -1
  4. package/dist/Collide2.d.ts.map +1 -1
  5. package/dist/Collide2.js +10 -6
  6. package/dist/Collide2.js.map +1 -1
  7. package/dist/FlowField.d.ts.map +1 -1
  8. package/dist/FlowField.js +2 -1
  9. package/dist/FlowField.js.map +1 -1
  10. package/dist/InputAxis.js +1 -1
  11. package/dist/Ops.d.ts +209 -0
  12. package/dist/Ops.d.ts.map +1 -0
  13. package/dist/Ops.js +210 -0
  14. package/dist/Ops.js.map +1 -0
  15. package/dist/Random.d.ts +63 -10
  16. package/dist/Random.d.ts.map +1 -1
  17. package/dist/Random.js +57 -32
  18. package/dist/Random.js.map +1 -1
  19. package/dist/Scalar.d.ts +7 -2
  20. package/dist/Scalar.d.ts.map +1 -1
  21. package/dist/Scalar.js +2 -1
  22. package/dist/Scalar.js.map +1 -1
  23. package/dist/SpatialGrid.d.ts +7 -2
  24. package/dist/SpatialGrid.d.ts.map +1 -1
  25. package/dist/SpatialGrid.js +35 -4
  26. package/dist/SpatialGrid.js.map +1 -1
  27. package/dist/Vec2.d.ts.map +1 -1
  28. package/dist/Vec2.js +8 -7
  29. package/dist/Vec2.js.map +1 -1
  30. package/dist/Vector2.d.ts +12 -0
  31. package/dist/Vector2.d.ts.map +1 -1
  32. package/dist/Vector2.js +12 -0
  33. package/dist/Vector2.js.map +1 -1
  34. package/dist/index.d.ts +5 -0
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +5 -0
  37. package/dist/index.js.map +1 -1
  38. package/dist/internal/fdlibm.d.ts +43 -0
  39. package/dist/internal/fdlibm.d.ts.map +1 -0
  40. package/dist/internal/fdlibm.js +1291 -0
  41. package/dist/internal/fdlibm.js.map +1 -0
  42. package/dist/internal/vector2.d.ts.map +1 -1
  43. package/dist/internal/vector2.js +2 -1
  44. package/dist/internal/vector2.js.map +1 -1
  45. package/package.json +3 -2
  46. package/src/Collide2.ts +10 -6
  47. package/src/FlowField.ts +2 -1
  48. package/src/InputAxis.ts +1 -1
  49. package/src/Ops.ts +232 -0
  50. package/src/Random.ts +104 -16
  51. package/src/Scalar.ts +7 -2
  52. package/src/SpatialGrid.ts +40 -6
  53. package/src/Vec2.ts +9 -7
  54. package/src/Vector2.ts +12 -0
  55. package/src/index.ts +5 -0
  56. package/src/internal/fdlibm.ts +1256 -0
  57. package/src/internal/vector2.ts +2 -1
package/dist/Ops.js ADDED
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Math functions that return the same bits on every JavaScript engine and
3
+ * CPU, so a simulation replays exactly on any device.
4
+ *
5
+ * The spec lets engines approximate `Math.sin`, `cos`, `tan`, `asin`, `acos`,
6
+ * `atan`, `atan2`, `exp`, `expm1`, `log`, `log2`, `log10`, `log1p`, `sinh`,
7
+ * `cosh`, `tanh`, `asinh`, `acosh`, `atanh`, `cbrt`, `pow`, `hypot`, and
8
+ * `a ** b`, and they do: Chrome, Safari, macOS, and Linux disagree in the
9
+ * last bit, and a simulation grows that bit into a different run. Use these
10
+ * in simulation code instead; each is a pure-JavaScript port of fdlibm (musl
11
+ * libm) built only from operations every engine rounds exactly.
12
+ *
13
+ * Keep using `Math.abs`, `sign`, `min`, `max`, `floor`, `ceil`, `round`,
14
+ * `trunc`, `sqrt`, `imul`, `fround`, `+ - * /`, and `x ** 2`: they are
15
+ * already exact everywhere. Use `Random` for randomness and `Clock` for time.
16
+ * Code that only draws (rendering, effects) can use `Math` freely. The
17
+ * `ritmo/use-ops-for-math` rule (`@typeonce/oxlint-plugin-ritmo`) points
18
+ * simulation code here.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * // Inside a system: aim, then move along the heading.
23
+ * const heading = Ops.atan2(target.y - position.y, target.x - position.x)
24
+ * const step = { x: Ops.cos(heading) * speed * dt, y: Ops.sin(heading) * speed * dt }
25
+ * const damping = Ops.exp(-friction * dt)
26
+ * ```
27
+ *
28
+ * @module Ops
29
+ * @docGroup helpers
30
+ *
31
+ * @categoryDescription Trigonometry
32
+ * Sine, cosine, tangent, and their inverses, in radians.
33
+ *
34
+ * @categoryDescription Exponentials
35
+ * Exponentials, logarithms, powers, and roots.
36
+ *
37
+ * @categoryDescription Hyperbolic
38
+ * Hyperbolic functions and their inverses.
39
+ *
40
+ * @categoryDescription Lengths
41
+ * Euclidean length without overflow.
42
+ */
43
+ import * as fdlibm from "./internal/fdlibm.js";
44
+ /**
45
+ * Sine of `x` radians. Same bits on every engine (within 1 ulp of the exact
46
+ * value); use instead of `Math.sin` in simulation code.
47
+ *
48
+ * @category Trigonometry
49
+ */
50
+ export const sin = fdlibm.sin;
51
+ /**
52
+ * Cosine of `x` radians. Same bits on every engine (within 1 ulp of the
53
+ * exact value); use instead of `Math.cos` in simulation code.
54
+ *
55
+ * @category Trigonometry
56
+ */
57
+ export const cos = fdlibm.cos;
58
+ /**
59
+ * Tangent of `x` radians. Same bits on every engine (within 1 ulp of the
60
+ * exact value); use instead of `Math.tan` in simulation code.
61
+ *
62
+ * @category Trigonometry
63
+ */
64
+ export const tan = fdlibm.tan;
65
+ /**
66
+ * Arcsine of `x` in radians, in [-π/2, π/2]; NaN outside [-1, 1]. Same bits
67
+ * on every engine; use instead of `Math.asin` in simulation code.
68
+ *
69
+ * @category Trigonometry
70
+ */
71
+ export const asin = fdlibm.asin;
72
+ /**
73
+ * Arccosine of `x` in radians, in [0, π]; NaN outside [-1, 1]. Same bits on
74
+ * every engine; use instead of `Math.acos` in simulation code.
75
+ *
76
+ * @category Trigonometry
77
+ */
78
+ export const acos = fdlibm.acos;
79
+ /**
80
+ * Arctangent of `x` in radians, in (-π/2, π/2). Same bits on every engine;
81
+ * use instead of `Math.atan` in simulation code. For the angle of a vector,
82
+ * use `atan2`.
83
+ *
84
+ * @category Trigonometry
85
+ */
86
+ export const atan = fdlibm.atan;
87
+ /**
88
+ * The angle of the vector (x, y) in radians, in [-π, π] (note the argument
89
+ * order: `y` first, like `Math.atan2`). Same bits on every engine; use
90
+ * instead of `Math.atan2` in simulation code.
91
+ *
92
+ * @category Trigonometry
93
+ */
94
+ export const atan2 = fdlibm.atan2;
95
+ /**
96
+ * e raised to `x`. Same bits on every engine (within 1 ulp of the exact
97
+ * value); use instead of `Math.exp` in simulation code, for example for
98
+ * frame-rate independent damping `exp(-rate * dt)`.
99
+ *
100
+ * @category Exponentials
101
+ */
102
+ export const exp = fdlibm.exp;
103
+ /**
104
+ * Hyperbolic tangent of `x`, in [-1, 1]. Same bits on every engine (within 2
105
+ * ulp of the exact value, like the native one); use instead of `Math.tanh` in
106
+ * simulation code.
107
+ *
108
+ * @category Hyperbolic
109
+ */
110
+ export const tanh = fdlibm.tanh;
111
+ /**
112
+ * e raised to `x`, minus 1, accurate for `x` near 0 (where `exp(x) - 1` loses
113
+ * digits). Same bits on every engine; use instead of `Math.expm1` in
114
+ * simulation code.
115
+ *
116
+ * @category Exponentials
117
+ */
118
+ export const expm1 = fdlibm.expm1;
119
+ /**
120
+ * Natural logarithm of `x`: -Infinity at 0, NaN below 0. Same bits on every
121
+ * engine (within 1 ulp of the exact value); use instead of `Math.log` in
122
+ * simulation code.
123
+ *
124
+ * @category Exponentials
125
+ */
126
+ export const log = fdlibm.log;
127
+ /**
128
+ * Base-2 logarithm of `x`: -Infinity at 0, NaN below 0, exact for powers of
129
+ * two. Same bits on every engine; use instead of `Math.log2` in simulation
130
+ * code.
131
+ *
132
+ * @category Exponentials
133
+ */
134
+ export const log2 = fdlibm.log2;
135
+ /**
136
+ * Base-10 logarithm of `x`: -Infinity at 0, NaN below 0. Same bits on every
137
+ * engine; use instead of `Math.log10` in simulation code.
138
+ *
139
+ * @category Exponentials
140
+ */
141
+ export const log10 = fdlibm.log10;
142
+ /**
143
+ * Natural logarithm of `1 + x`, accurate for `x` near 0 (where `log(1 + x)`
144
+ * loses digits). Same bits on every engine; use instead of `Math.log1p` in
145
+ * simulation code.
146
+ *
147
+ * @category Exponentials
148
+ */
149
+ export const log1p = fdlibm.log1p;
150
+ /**
151
+ * Cube root of `x`, negative for negative `x`. Same bits on every engine;
152
+ * use instead of `Math.cbrt` and `x ** (1 / 3)` in simulation code.
153
+ *
154
+ * @category Exponentials
155
+ */
156
+ export const cbrt = fdlibm.cbrt;
157
+ /**
158
+ * `base` raised to `exponent`, with the results of `base ** exponent` for
159
+ * every special case (NaN, zeros, infinities, negative bases). Same bits on
160
+ * every engine (within 1 ulp of the exact value); use instead of `Math.pow`
161
+ * and `**` in simulation code. `x * x` and `x ** 2` are already exact.
162
+ *
163
+ * @category Exponentials
164
+ */
165
+ export const pow = fdlibm.pow;
166
+ /**
167
+ * Hyperbolic sine of `x`. Same bits on every engine (within 1 ulp of the
168
+ * exact value); use instead of `Math.sinh` in simulation code.
169
+ *
170
+ * @category Hyperbolic
171
+ */
172
+ export const sinh = fdlibm.sinh;
173
+ /**
174
+ * Hyperbolic cosine of `x`, at least 1. Same bits on every engine (within 1
175
+ * ulp of the exact value); use instead of `Math.cosh` in simulation code.
176
+ *
177
+ * @category Hyperbolic
178
+ */
179
+ export const cosh = fdlibm.cosh;
180
+ /**
181
+ * Inverse hyperbolic sine of `x`. Same bits on every engine; use instead of
182
+ * `Math.asinh` in simulation code.
183
+ *
184
+ * @category Hyperbolic
185
+ */
186
+ export const asinh = fdlibm.asinh;
187
+ /**
188
+ * Inverse hyperbolic cosine of `x`: NaN below 1. Same bits on every engine;
189
+ * use instead of `Math.acosh` in simulation code.
190
+ *
191
+ * @category Hyperbolic
192
+ */
193
+ export const acosh = fdlibm.acosh;
194
+ /**
195
+ * Inverse hyperbolic tangent of `x`: ±Infinity at ±1, NaN beyond. Same bits
196
+ * on every engine; use instead of `Math.atanh` in simulation code.
197
+ *
198
+ * @category Hyperbolic
199
+ */
200
+ export const atanh = fdlibm.atanh;
201
+ /**
202
+ * The length of the vector (x, y), `sqrt(x² + y²)` without overflow or
203
+ * underflow. Same bits on every engine (within 1 ulp of the exact value);
204
+ * use instead of `Math.hypot` in simulation code. Takes exactly two numbers;
205
+ * for vectors use `Vec2.length` and `Vec2.distance`.
206
+ *
207
+ * @category Lengths
208
+ */
209
+ export const hypot = fdlibm.hypot;
210
+ //# sourceMappingURL=Ops.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Ops.js","sourceRoot":"","sources":["../src/Ops.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,OAAO,KAAK,MAAM,MAAM,sBAAsB,CAAA;AAE9C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,GAAG,GAA0B,MAAM,CAAC,GAAG,CAAA;AAEpD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,GAAG,GAA0B,MAAM,CAAC,GAAG,CAAA;AAEpD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,GAAG,GAA0B,MAAM,CAAC,GAAG,CAAA;AAEpD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAA0B,MAAM,CAAC,IAAI,CAAA;AAEtD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAA0B,MAAM,CAAC,IAAI,CAAA;AAEtD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,IAAI,GAA0B,MAAM,CAAC,IAAI,CAAA;AAEtD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,KAAK,GAAqC,MAAM,CAAC,KAAK,CAAA;AAEnE;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,GAAG,GAA0B,MAAM,CAAC,GAAG,CAAA;AAEpD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,IAAI,GAA0B,MAAM,CAAC,IAAI,CAAA;AAEtD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,KAAK,GAA0B,MAAM,CAAC,KAAK,CAAA;AAExD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,GAAG,GAA0B,MAAM,CAAC,GAAG,CAAA;AAEpD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,IAAI,GAA0B,MAAM,CAAC,IAAI,CAAA;AAEtD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,KAAK,GAA0B,MAAM,CAAC,KAAK,CAAA;AAExD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,KAAK,GAA0B,MAAM,CAAC,KAAK,CAAA;AAExD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAA0B,MAAM,CAAC,IAAI,CAAA;AAEtD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,GAAG,GAA+C,MAAM,CAAC,GAAG,CAAA;AAEzE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAA0B,MAAM,CAAC,IAAI,CAAA;AAEtD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAA0B,MAAM,CAAC,IAAI,CAAA;AAEtD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,KAAK,GAA0B,MAAM,CAAC,KAAK,CAAA;AAExD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,KAAK,GAA0B,MAAM,CAAC,KAAK,CAAA;AAExD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,KAAK,GAA0B,MAAM,CAAC,KAAK,CAAA;AAExD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,KAAK,GAAqC,MAAM,CAAC,KAAK,CAAA"}
package/dist/Random.d.ts CHANGED
@@ -3,16 +3,22 @@
3
3
  * integer.
4
4
  *
5
5
  * Keep the state in a resource, so a run replays exactly and saves with the
6
- * world: a system makes a generator from the stored state, draws from it,
7
- * then writes `random.state` back. Two generators made from the same state
8
- * draw the same sequence on every platform.
6
+ * world: declare it with this module as its validator, start it with
7
+ * `seed`, and draw in systems through `draw` over its write cell, which writes
8
+ * every draw back (rolled back with a failed system). Two generators made
9
+ * from the same state draw the same sequence on every platform. `make` is for
10
+ * a state that lives outside the world (a level generator seeded once).
9
11
  *
10
12
  * @example
11
13
  * ```ts
12
- * const random = Random.make(resources.rng.get().state)
13
- * const angle = random.range(0, Math.PI * 2)
14
- * const kind = random.pick(kinds) ?? "grunt"
15
- * resources.rng.set({ state: random.state })
14
+ * const Rng = Descriptor.ConstructedResource(Random)("Game/Rng")
15
+ * const runtime = Game.Runtime.make({ services, resources: { Rng: Random.seed(0x5eed) } })
16
+ *
17
+ * Game.System("Game/Spawn", { resources: { rng: Game.System.writeResource(Rng) } }, ({ resources }) => {
18
+ * const random = Random.draw(resources.rng)
19
+ * const angle = random.range(0, Math.PI * 2)
20
+ * const kind = random.pick(kinds) ?? "grunt"
21
+ * })
16
22
  * ```
17
23
  *
18
24
  * @module Random
@@ -23,7 +29,13 @@
23
29
  *
24
30
  * @categoryDescription Construction
25
31
  * Making a generator from a stored state.
32
+ *
33
+ * @categoryDescription Resource
34
+ * Keeping the state in a world resource.
26
35
  */
36
+ import type * as Brand from "@typeonce/ritmo/Brand";
37
+ import type { WriteCell } from "@typeonce/ritmo/Query";
38
+ import * as Result from "@typeonce/ritmo/Result";
27
39
  /**
28
40
  * A generator. Every draw advances `state`.
29
41
  *
@@ -34,9 +46,9 @@ export interface Random {
34
46
  readonly state: number;
35
47
  /** Uniform in [0, 1). */
36
48
  next(): number;
37
- /** Uniform in [min, max). */
49
+ /** Uniform in [min, max), or `min` when they are equal. Throws when `min > max` or a bound is not finite. */
38
50
  range(min: number, max: number): number;
39
- /** A uniform integer in [min, maxExclusive); both bounds are integers with min < maxExclusive. */
51
+ /** A uniform integer in [min, maxExclusive). Throws unless both bounds are integers with min < maxExclusive. */
40
52
  integer(min: number, maxExclusive: number): number;
41
53
  /** A uniform element of `items`, or `undefined` when it is empty (no draw is made then). */
42
54
  pick<A>(items: ReadonlyArray<A>): A | undefined;
@@ -46,7 +58,7 @@ export interface Random {
46
58
  * An element of `items` chosen with probability proportional to `weight`,
47
59
  * or `undefined` when no element has a positive finite weight (no draw is
48
60
  * made then). Elements with zero, negative, or non-finite weight are never
49
- * chosen.
61
+ * chosen. `weight` is called once per element.
50
62
  */
51
63
  weighted<A>(items: ReadonlyArray<A>, weight: (item: A) => number): A | undefined;
52
64
  }
@@ -58,4 +70,45 @@ export interface Random {
58
70
  * @category Construction
59
71
  */
60
72
  export declare const make: (state: number) => Random;
73
+ /**
74
+ * A generator's state as a resource holds it: an unsigned 32-bit integer.
75
+ * Only `seed`, `result`, and `decode` make one, so `draw` takes the cell of a
76
+ * random resource and nothing else.
77
+ *
78
+ * @category Resource
79
+ */
80
+ export type State = Brand.Branded<number, "Random/State">;
81
+ /** Why a value is not a generator state. @category Resource */
82
+ export interface InvalidState {
83
+ readonly _tag: "InvalidRandomState";
84
+ readonly value: unknown;
85
+ }
86
+ /**
87
+ * Validates a state, for `Descriptor.ConstructedResource(Random)` and saves.
88
+ *
89
+ * @category Resource
90
+ */
91
+ export declare const result: (raw: number) => Result.Result<State, InvalidState>;
92
+ /**
93
+ * Validates a state read from untrusted data (a save).
94
+ *
95
+ * @category Resource
96
+ */
97
+ export declare const decode: (raw: unknown) => Result.Result<State, InvalidState>;
98
+ /**
99
+ * The starting state for a seed, reduced to an unsigned 32-bit integer like
100
+ * `make`: the value to give a random resource in `Game.Runtime.make`.
101
+ *
102
+ * @category Resource
103
+ */
104
+ export declare const seed: (value: number) => State;
105
+ /**
106
+ * A generator over a random resource's write cell: every draw continues from
107
+ * the stored state and writes the new one back, so the system needs no
108
+ * `set` of its own, a failed run rolls the draws back, and generators made
109
+ * from the same cell in one run continue one sequence.
110
+ *
111
+ * @category Resource
112
+ */
113
+ export declare const draw: (cell: WriteCell<State>) => Random;
61
114
  //# sourceMappingURL=Random.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Random.d.ts","sourceRoot":"","sources":["../src/Random.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH;;;;GAIG;AACH,MAAM,WAAW,MAAM;IACrB,8FAA8F;IAC9F,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,yBAAyB;IACzB,IAAI,IAAI,MAAM,CAAA;IACd,6BAA6B;IAC7B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;IACvC,kGAAkG;IAClG,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAAA;IAClD,4FAA4F;IAC5F,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAAA;IAC/C,iDAAiD;IACjD,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;IAC7C;;;;;OAKG;IACH,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GAAG,CAAC,GAAG,SAAS,CAAA;CACjF;AA+DD;;;;;;GAMG;AACH,eAAO,MAAM,IAAI,UAAW,MAAM,KAAG,MAA+B,CAAA"}
1
+ {"version":3,"file":"Random.d.ts","sourceRoot":"","sources":["../src/Random.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,KAAK,KAAK,KAAK,MAAM,uBAAuB,CAAA;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,KAAK,MAAM,MAAM,wBAAwB,CAAA;AAEhD;;;;GAIG;AACH,MAAM,WAAW,MAAM;IACrB,8FAA8F;IAC9F,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,yBAAyB;IACzB,IAAI,IAAI,MAAM,CAAA;IACd,6GAA6G;IAC7G,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;IACvC,gHAAgH;IAChH,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAAA;IAClD,4FAA4F;IAC5F,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAAA;IAC/C,iDAAiD;IACjD,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;IAC7C;;;;;OAKG;IACH,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GAAG,CAAC,GAAG,SAAS,CAAA;CACjF;AAsED;;;;;;GAMG;AACH,eAAO,MAAM,IAAI,UAAW,MAAM,KAAG,MAA+B,CAAA;AAEpE;;;;;;GAMG;AACH,MAAM,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;AAEzD,+DAA+D;AAC/D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAA;IACnC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CACxB;AAKD;;;;GAIG;AACH,eAAO,MAAM,MAAM,QAAS,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,YAAY,CAC2B,CAAA;AAEjG;;;;GAIG;AACH,eAAO,MAAM,MAAM,QAAS,OAAO,KAAG,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,YAAY,CAC0B,CAAA;AAEjG;;;;;GAKG;AACH,eAAO,MAAM,IAAI,UAAW,MAAM,KAAG,KAA+B,CAAA;AAmBpE;;;;;;;GAOG;AACH,eAAO,MAAM,IAAI,SAAU,SAAS,CAAC,KAAK,CAAC,KAAG,MAA8B,CAAA"}
package/dist/Random.js CHANGED
@@ -1,29 +1,4 @@
1
- /**
2
- * Deterministic random numbers (mulberry32) whose whole state is one 32-bit
3
- * integer.
4
- *
5
- * Keep the state in a resource, so a run replays exactly and saves with the
6
- * world: a system makes a generator from the stored state, draws from it,
7
- * then writes `random.state` back. Two generators made from the same state
8
- * draw the same sequence on every platform.
9
- *
10
- * @example
11
- * ```ts
12
- * const random = Random.make(resources.rng.get().state)
13
- * const angle = random.range(0, Math.PI * 2)
14
- * const kind = random.pick(kinds) ?? "grunt"
15
- * resources.rng.set({ state: random.state })
16
- * ```
17
- *
18
- * @module Random
19
- * @docGroup helpers
20
- *
21
- * @categoryDescription Random Types
22
- * The generator interface.
23
- *
24
- * @categoryDescription Construction
25
- * Making a generator from a stored state.
26
- */
1
+ import * as Result from "@typeonce/ritmo/Result";
27
2
  const usable = (weight) => weight > 0 && weight < Infinity;
28
3
  class Mulberry32 {
29
4
  state;
@@ -38,9 +13,15 @@ class Mulberry32 {
38
13
  return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
39
14
  }
40
15
  range(min, max) {
16
+ if (!(Number.isFinite(min) && Number.isFinite(max) && min <= max)) {
17
+ throw new Error(`Random.range needs finite bounds with min <= max, got [${min}, ${max})`);
18
+ }
41
19
  return min + (max - min) * this.next();
42
20
  }
43
21
  integer(min, maxExclusive) {
22
+ if (!(Number.isSafeInteger(min) && Number.isSafeInteger(maxExclusive) && min < maxExclusive)) {
23
+ throw new Error(`Random.integer needs whole bounds with min below maxExclusive, got [${min}, ${maxExclusive})`);
24
+ }
44
25
  return min + Math.floor(this.next() * (maxExclusive - min));
45
26
  }
46
27
  pick(items) {
@@ -57,9 +38,10 @@ class Mulberry32 {
57
38
  return shuffled;
58
39
  }
59
40
  weighted(items, weight) {
41
+ // `weight` is called once per item: it may be costly or not pure.
42
+ const weights = items.map(weight);
60
43
  let total = 0;
61
- for (const item of items) {
62
- const value = weight(item);
44
+ for (const value of weights) {
63
45
  if (usable(value))
64
46
  total += value;
65
47
  }
@@ -67,14 +49,14 @@ class Mulberry32 {
67
49
  return undefined;
68
50
  let roll = this.next() * total;
69
51
  let last;
70
- for (const item of items) {
71
- const value = weight(item);
52
+ for (let index = 0; index < items.length; index++) {
53
+ const value = weights[index];
72
54
  if (!usable(value))
73
55
  continue;
74
- last = item;
56
+ last = items[index];
75
57
  roll -= value;
76
58
  if (roll < 0)
77
- return item;
59
+ return items[index];
78
60
  }
79
61
  // Rounding can leave a sliver of the roll past the last bucket.
80
62
  return last;
@@ -88,4 +70,47 @@ class Mulberry32 {
88
70
  * @category Construction
89
71
  */
90
72
  export const make = (state) => new Mulberry32(state);
73
+ const isState = (value) => typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 0xffffffff;
74
+ /**
75
+ * Validates a state, for `Descriptor.ConstructedResource(Random)` and saves.
76
+ *
77
+ * @category Resource
78
+ */
79
+ export const result = (raw) => isState(raw) ? Result.success(raw) : Result.failure({ _tag: "InvalidRandomState", value: raw });
80
+ /**
81
+ * Validates a state read from untrusted data (a save).
82
+ *
83
+ * @category Resource
84
+ */
85
+ export const decode = (raw) => isState(raw) ? Result.success(raw) : Result.failure({ _tag: "InvalidRandomState", value: raw });
86
+ /**
87
+ * The starting state for a seed, reduced to an unsigned 32-bit integer like
88
+ * `make`: the value to give a random resource in `Game.Runtime.make`.
89
+ *
90
+ * @category Resource
91
+ */
92
+ export const seed = (value) => (value >>> 0);
93
+ class CellRandom extends Mulberry32 {
94
+ #cell;
95
+ constructor(cell) {
96
+ super(cell.get());
97
+ this.#cell = cell;
98
+ }
99
+ next() {
100
+ // Read the cell each time, so two generators over one cell share one sequence.
101
+ this.state = this.#cell.get();
102
+ const value = super.next();
103
+ this.#cell.set(this.state);
104
+ return value;
105
+ }
106
+ }
107
+ /**
108
+ * A generator over a random resource's write cell: every draw continues from
109
+ * the stored state and writes the new one back, so the system needs no
110
+ * `set` of its own, a failed run rolls the draws back, and generators made
111
+ * from the same cell in one run continue one sequence.
112
+ *
113
+ * @category Resource
114
+ */
115
+ export const draw = (cell) => new CellRandom(cell);
91
116
  //# sourceMappingURL=Random.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Random.js","sourceRoot":"","sources":["../src/Random.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Random.js","sourceRoot":"","sources":["../src/Random.ts"],"names":[],"mappings":"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"}
package/dist/Scalar.d.ts CHANGED
@@ -39,7 +39,11 @@ import type * as Result from "@typeonce/ritmo/Result";
39
39
  * Finite number brand.
40
40
  *
41
41
  * Values of this type are guaranteed not to be `NaN`, `Infinity`, or
42
- * `-Infinity`.
42
+ * `-Infinity` when they come from a validator (`result`, `decode`). The
43
+ * arithmetic helpers here and in `Vector2` keep the brand without
44
+ * re-validating, so their results are finite only while they stay within
45
+ * `±Number.MAX_VALUE`: game-sized values never come close, but validate
46
+ * again with `result` when inputs may be that large.
43
47
  *
44
48
  * @category Scalar Types
45
49
  */
@@ -112,7 +116,8 @@ export declare const clamp: (value: Finite, min: Finite, max: Finite) => Finite;
112
116
  * Interpolates between two finite values by one finite amount.
113
117
  *
114
118
  * The amount is not clamped. This stays a pure interpolation primitive rather
115
- * than mixing interpolation with policy.
119
+ * than mixing interpolation with policy. The result keeps the `Finite` brand
120
+ * without re-validating (see `Finite`).
116
121
  *
117
122
  * @category Operations
118
123
  */
@@ -1 +1 @@
1
- {"version":3,"file":"Scalar.d.ts","sourceRoot":"","sources":["../src/Scalar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,KAAK,KAAK,KAAK,MAAM,uBAAuB,CAAA;AAEnD,OAAO,KAAK,KAAK,MAAM,MAAM,wBAAwB,CAAA;AAErD;;;;;;;GAOG;AACH,MAAM,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;AAC3D;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAA;AACrE;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;AAE/D;;;;GAIG;AACH,MAAM,MAAM,KAAK,GACb;IAAE,QAAQ,CAAC,GAAG,EAAE,kBAAkB,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,QAAQ,CAAC,GAAG,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,QAAQ,CAAC,GAAG,EAAE,oBAAoB,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAElE;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,GAAG,EAAE,kBAAkB,CAAA;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,MAAM,0CAAkB,CAAA;AACrC;;;;GAIG;AACH,eAAO,MAAM,WAAW,+CAAuB,CAAA;AAC/C;;;;GAIG;AACH,eAAO,MAAM,QAAQ,4CAAoB,CAAA;AAEzC;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAuB,CAAA;AACxF;;;;;;;GAOG;AACH,eAAO,MAAM,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,MAAsB,CAAA;AACzF;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,KAAK,MAA0B,CAAA;AAC7G;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,EAAE,CACxB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,KACV,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAwB,CAAA;AACrE;;;;;;GAMG;AACH,eAAO,MAAM,KAAK,EAAE,CAClB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,KACd,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAkB,CAAA;AAE/D;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA"}
1
+ {"version":3,"file":"Scalar.d.ts","sourceRoot":"","sources":["../src/Scalar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,KAAK,KAAK,KAAK,MAAM,uBAAuB,CAAA;AAEnD,OAAO,KAAK,KAAK,MAAM,MAAM,wBAAwB,CAAA;AAErD;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;AAC3D;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAA;AACrE;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;AAE/D;;;;GAIG;AACH,MAAM,MAAM,KAAK,GACb;IAAE,QAAQ,CAAC,GAAG,EAAE,kBAAkB,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,QAAQ,CAAC,GAAG,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,QAAQ,CAAC,GAAG,EAAE,oBAAoB,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAElE;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,GAAG,EAAE,kBAAkB,CAAA;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,MAAM,0CAAkB,CAAA;AACrC;;;;GAIG;AACH,eAAO,MAAM,WAAW,+CAAuB,CAAA;AAC/C;;;;GAIG;AACH,eAAO,MAAM,QAAQ,4CAAoB,CAAA;AAEzC;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAuB,CAAA;AACxF;;;;;;;;GAQG;AACH,eAAO,MAAM,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,MAAsB,CAAA;AACzF;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,KAAK,MAA0B,CAAA;AAC7G;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,EAAE,CACxB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,KACV,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAwB,CAAA;AACrE;;;;;;GAMG;AACH,eAAO,MAAM,KAAK,EAAE,CAClB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,KACd,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAkB,CAAA;AAE/D;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA"}
package/dist/Scalar.js CHANGED
@@ -30,7 +30,8 @@ export const clamp = internal.clamp;
30
30
  * Interpolates between two finite values by one finite amount.
31
31
  *
32
32
  * The amount is not clamped. This stays a pure interpolation primitive rather
33
- * than mixing interpolation with policy.
33
+ * than mixing interpolation with policy. The result keeps the `Finite` brand
34
+ * without re-validating (see `Finite`).
34
35
  *
35
36
  * @category Operations
36
37
  */
@@ -1 +1 @@
1
- {"version":3,"file":"Scalar.js","sourceRoot":"","sources":["../src/Scalar.ts"],"names":[],"mappings":"AAoCA,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAA;AA8ChD;;;;GAIG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAA;AACrC;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAA;AAC/C;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAA;AAEzC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,KAAK,GAAwD,QAAQ,CAAC,KAAK,CAAA;AACxF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,IAAI,GAA2D,QAAQ,CAAC,IAAI,CAAA;AACzF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAuE,QAAQ,CAAC,QAAQ,CAAA;AAC7G;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,WAAW,GAIyB,QAAQ,CAAC,WAAW,CAAA;AACrE;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,KAAK,GAM+B,QAAQ,CAAC,KAAK,CAAA"}
1
+ {"version":3,"file":"Scalar.js","sourceRoot":"","sources":["../src/Scalar.ts"],"names":[],"mappings":"AAoCA,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAA;AAkDhD;;;;GAIG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAA;AACrC;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAA;AAC/C;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAA;AAEzC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,KAAK,GAAwD,QAAQ,CAAC,KAAK,CAAA;AACxF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,IAAI,GAA2D,QAAQ,CAAC,IAAI,CAAA;AACzF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAuE,QAAQ,CAAC,QAAQ,CAAA;AAC7G;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,WAAW,GAIyB,QAAQ,CAAC,WAAW,CAAA;AACrE;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,KAAK,GAM+B,QAAQ,CAAC,KAAK,CAAA"}
@@ -44,11 +44,16 @@ export interface SpatialGrid {
44
44
  readonly cellSize: Scalar.Positive;
45
45
  /** Removes every circle, keeping the storage for the next rebuild. */
46
46
  clear(): void;
47
- /** Adds circle `index` (a non-negative integer) covering `[x ± r] × [y ± r]`. */
47
+ /**
48
+ * Adds circle `index` (a non-negative integer) covering `[x ± r] × [y ± r]`.
49
+ * A non-finite coordinate or radius throws: it would cover no cell or all of them.
50
+ */
48
51
  insert(index: number, x: number, y: number, r: number): void;
49
52
  /**
50
53
  * Calls `visit` once for every circle whose cells overlap the box, in no
51
- * particular order. `visit` must not insert into or query this grid.
54
+ * particular order. `visit` must not insert into or query this grid. A
55
+ * non-finite bound throws (an unbounded box would never finish); a box
56
+ * covering more cells than are occupied scans the occupied cells instead.
52
57
  */
53
58
  forEachIn(minX: number, minY: number, maxX: number, maxY: number, visit: (index: number) => void): void;
54
59
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SpatialGrid.d.ts","sourceRoot":"","sources":["../src/SpatialGrid.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,KAAK,KAAK,MAAM,MAAM,aAAa,CAAA;AAE1C;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAA;IAClC,sEAAsE;IACtE,KAAK,IAAI,IAAI,CAAA;IACb,iFAAiF;IACjF,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5D;;;OAGG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAA;CACxG;AA4ED;;;;;;GAMG;AACH,eAAO,MAAM,IAAI,aAAc,MAAM,CAAC,QAAQ,KAAG,WAAiC,CAAA"}
1
+ {"version":3,"file":"SpatialGrid.d.ts","sourceRoot":"","sources":["../src/SpatialGrid.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,KAAK,KAAK,MAAM,MAAM,aAAa,CAAA;AAE1C;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAA;IAClC,sEAAsE;IACtE,KAAK,IAAI,IAAI,CAAA;IACb;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5D;;;;;OAKG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAA;CACxG;AAyGD;;;;;;GAMG;AACH,eAAO,MAAM,IAAI,aAAc,MAAM,CAAC,QAAQ,KAAG,WAAiC,CAAA"}
@@ -1,4 +1,13 @@
1
1
  const key = (cx, cy) => ((cx + 32768) << 16) | ((cy + 32768) & 0xffff);
2
+ // Keys repeat every 65,536 cells, so a longer span visits nothing new.
3
+ const AXIS_CELLS = 65_536;
4
+ const lastCell = (first, last) => Math.min(last, first + AXIS_CELLS - 1);
5
+ /** Whether a cell coordinate packed in a key falls in `[first, last]`, counting the keys' wrap-around. */
6
+ const coveredBy = (coordinate, first, last) => (((coordinate - first) % AXIS_CELLS) + AXIS_CELLS) % AXIS_CELLS <= last - first;
7
+ const notFinite = (operation, ...values) => {
8
+ const value = values.find((value) => !Number.isFinite(value));
9
+ throw new Error(`SpatialGrid.${operation} needs finite numbers, got ${value}`);
10
+ };
2
11
  class Grid {
3
12
  cellSize;
4
13
  cells = new Map();
@@ -15,11 +24,14 @@ class Grid {
15
24
  this.used.length = 0;
16
25
  }
17
26
  insert(index, x, y, r) {
27
+ // `x - x === 0` is false only for NaN and ±Infinity, without a call per number.
28
+ if (x - x !== 0 || y - y !== 0 || r - r !== 0)
29
+ notFinite("insert", x, y, r);
18
30
  const size = this.cellSize;
19
31
  const minX = Math.floor((x - r) / size);
20
- const maxX = Math.floor((x + r) / size);
32
+ const maxX = lastCell(minX, Math.floor((x + r) / size));
21
33
  const minY = Math.floor((y - r) / size);
22
- const maxY = Math.floor((y + r) / size);
34
+ const maxY = lastCell(minY, Math.floor((y + r) / size));
23
35
  for (let cx = minX; cx <= maxX; cx++) {
24
36
  for (let cy = minY; cy <= maxY; cy++) {
25
37
  const cellKey = key(cx, cy);
@@ -40,6 +52,8 @@ class Grid {
40
52
  }
41
53
  }
42
54
  forEachIn(minX, minY, maxX, maxY, visit) {
55
+ if (minX - minX !== 0 || minY - minY !== 0 || maxX - maxX !== 0 || maxY - maxY !== 0)
56
+ notFinite("forEachIn", minX, minY, maxX, maxY);
43
57
  const size = this.cellSize;
44
58
  // Start the marks over before the counter leaves the stamps' range (after
45
59
  // about two billion queries), so old marks never match a new query.
@@ -51,9 +65,26 @@ class Grid {
51
65
  const query = this.query;
52
66
  const stamp = this.stamp;
53
67
  const x0 = Math.floor(minX / size);
54
- const x1 = Math.floor(maxX / size);
68
+ const x1 = lastCell(x0, Math.floor(maxX / size));
55
69
  const y0 = Math.floor(minY / size);
56
- const y1 = Math.floor(maxY / size);
70
+ const y1 = lastCell(y0, Math.floor(maxY / size));
71
+ if ((x1 - x0 + 1) * (y1 - y0 + 1) > this.cells.size) {
72
+ // A box larger than the occupied area: scan the cells that exist.
73
+ for (const [cellKey, cell] of this.cells) {
74
+ if (cell.length === 0)
75
+ continue;
76
+ if (!coveredBy(((cellKey >> 16) & 0xffff) - 32768, x0, x1) || !coveredBy((cellKey & 0xffff) - 32768, y0, y1))
77
+ continue;
78
+ for (let offset = 0; offset < cell.length; offset++) {
79
+ const index = cell[offset];
80
+ if (stamp[index] === query)
81
+ continue;
82
+ stamp[index] = query;
83
+ visit(index);
84
+ }
85
+ }
86
+ return;
87
+ }
57
88
  for (let cx = x0; cx <= x1; cx++) {
58
89
  for (let cy = y0; cy <= y1; cy++) {
59
90
  const cell = this.cells.get(key(cx, cy));
@@ -1 +1 @@
1
- {"version":3,"file":"SpatialGrid.js","sourceRoot":"","sources":["../src/SpatialGrid.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SpatialGrid.js","sourceRoot":"","sources":["../src/SpatialGrid.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Vec2.d.ts","sourceRoot":"","sources":["../src/Vec2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;;;GAIG;AACH,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;GAIG;AACH,eAAO,MAAM,IAAI,EAAE,IAAoC,CAAA;AAEvD;;;;GAIG;AACH,eAAO,MAAM,GAAG,MAAO,IAAI,KAAK,IAAI,KAAG,IAAwC,CAAA;AAE/E;;;;GAIG;AACH,eAAO,MAAM,QAAQ,MAAO,IAAI,KAAK,IAAI,KAAG,IAAwC,CAAA;AAEpF;;;;GAIG;AACH,eAAO,MAAM,KAAK,MAAO,IAAI,UAAU,MAAM,KAAG,IAA8C,CAAA;AAE9F;;;;GAIG;AACH,eAAO,MAAM,MAAM,MAAO,IAAI,SAAS,MAAM,KAAG,IAI/C,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,GAAG,MAAO,IAAI,KAAK,IAAI,KAAG,MAA+B,CAAA;AAEtE;;;;GAIG;AACH,eAAO,MAAM,MAAM,MAAO,IAAI,KAAG,MAA8B,CAAA;AAE/D;;;;GAIG;AACH,eAAO,MAAM,aAAa,MAAO,IAAI,KAAG,MAA+B,CAAA;AAEvE;;;;GAIG;AACH,eAAO,MAAM,QAAQ,MAAO,IAAI,KAAK,IAAI,KAAG,MAA0C,CAAA;AAEtF;;;;GAIG;AACH,eAAO,MAAM,eAAe,MAAO,IAAI,KAAK,IAAI,KAAG,MAIlD,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,MAAO,IAAI,YAAY,IAAI,KAAG,IAGrD,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,IAAI,MAAO,IAAI,KAAK,IAAI,KAAK,MAAM,KAAG,IAAgE,CAAA;AAEnH;;;;GAIG;AACH,eAAO,MAAM,UAAU,YAAa,IAAI,UAAU,IAAI,YAAY,MAAM,KAAG,IAM1E,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,WAAW,MAAO,IAAI,OAAO,MAAM,KAAG,IAGlD,CAAA"}
1
+ {"version":3,"file":"Vec2.d.ts","sourceRoot":"","sources":["../src/Vec2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH;;;;GAIG;AACH,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;GAIG;AACH,eAAO,MAAM,IAAI,EAAE,IAAoC,CAAA;AAEvD;;;;GAIG;AACH,eAAO,MAAM,GAAG,MAAO,IAAI,KAAK,IAAI,KAAG,IAAwC,CAAA;AAE/E;;;;GAIG;AACH,eAAO,MAAM,QAAQ,MAAO,IAAI,KAAK,IAAI,KAAG,IAAwC,CAAA;AAEpF;;;;GAIG;AACH,eAAO,MAAM,KAAK,MAAO,IAAI,UAAU,MAAM,KAAG,IAA8C,CAAA;AAE9F;;;;GAIG;AACH,eAAO,MAAM,MAAM,MAAO,IAAI,SAAS,MAAM,KAAG,IAI/C,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,GAAG,MAAO,IAAI,KAAK,IAAI,KAAG,MAA+B,CAAA;AAEtE;;;;GAIG;AACH,eAAO,MAAM,MAAM,MAAO,IAAI,KAAG,MAA6B,CAAA;AAE9D;;;;GAIG;AACH,eAAO,MAAM,aAAa,MAAO,IAAI,KAAG,MAA+B,CAAA;AAEvE;;;;GAIG;AACH,eAAO,MAAM,QAAQ,MAAO,IAAI,KAAK,IAAI,KAAG,MAAyC,CAAA;AAErF;;;;GAIG;AACH,eAAO,MAAM,eAAe,MAAO,IAAI,KAAK,IAAI,KAAG,MAIlD,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,MAAO,IAAI,YAAY,IAAI,KAAG,IAGrD,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,IAAI,MAAO,IAAI,KAAK,IAAI,KAAK,MAAM,KAAG,IAAgE,CAAA;AAEnH;;;;GAIG;AACH,eAAO,MAAM,UAAU,YAAa,IAAI,UAAU,IAAI,YAAY,MAAM,KAAG,IAM1E,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,WAAW,MAAO,IAAI,OAAO,MAAM,KAAG,IAGlD,CAAA"}