@reicek/neataptic-ts 0.1.21 → 0.1.22

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 (223) hide show
  1. package/.github/agents/boundary-mapper.agent.md +29 -0
  2. package/.github/agents/docs-scout.agent.md +29 -0
  3. package/.github/agents/plan-scout.agent.md +29 -0
  4. package/.github/agents/solid-split.agent.md +138 -0
  5. package/.github/copilot-instructions.md +103 -0
  6. package/package.json +6 -3
  7. package/plans/ES2023 migration +13 -8
  8. package/plans/Evolution_Training_Interoperability_Contracts.md +1 -1
  9. package/plans/Interactive_Examples_and_Learning_Path.md +10 -2
  10. package/plans/Memory_Optimization.md +3 -3
  11. package/plans/README.md +63 -0
  12. package/plans/Roadmap.md +15 -3
  13. package/plans/asciiMaze_SOLID_split.done.md +130 -0
  14. package/plans/flappy_bird_SOLID_split.done.md +67 -0
  15. package/scripts/assets/theme.css +221 -34
  16. package/scripts/copy-examples.mjs +9 -5
  17. package/scripts/export-onnx.mjs +3 -3
  18. package/scripts/generate-bench-tables.mjs +10 -10
  19. package/scripts/generate-bench-tables.ts +10 -10
  20. package/scripts/generate-docs.ts +1415 -449
  21. package/scripts/render-docs-html.ts +15 -8
  22. package/src/README.md +101 -223
  23. package/src/architecture/README.md +57 -185
  24. package/src/architecture/layer/README.md +38 -38
  25. package/src/architecture/network/README.md +33 -31
  26. package/src/architecture/network/activate/README.md +77 -77
  27. package/src/architecture/network/connect/README.md +15 -13
  28. package/src/architecture/network/deterministic/README.md +7 -7
  29. package/src/architecture/network/evolve/README.md +44 -44
  30. package/src/architecture/network/gating/README.md +20 -20
  31. package/src/architecture/network/genetic/README.md +51 -51
  32. package/src/architecture/network/mutate/README.md +97 -97
  33. package/src/architecture/network/onnx/README.md +264 -264
  34. package/src/architecture/network/prune/README.md +39 -39
  35. package/src/architecture/network/remove/README.md +26 -26
  36. package/src/architecture/network/serialize/README.md +56 -56
  37. package/src/architecture/network/slab/README.md +61 -61
  38. package/src/architecture/network/standalone/README.md +24 -24
  39. package/src/architecture/network/stats/README.md +9 -9
  40. package/src/architecture/network/topology/README.md +46 -46
  41. package/src/architecture/network/training/README.md +21 -21
  42. package/src/methods/README.md +9 -87
  43. package/src/multithreading/README.md +8 -77
  44. package/src/multithreading/workers/README.md +2 -2
  45. package/src/multithreading/workers/browser/README.md +0 -6
  46. package/src/multithreading/workers/node/README.md +0 -3
  47. package/src/neat/README.md +562 -568
  48. package/src/utils/README.md +18 -18
  49. package/test/examples/asciiMaze/README.md +59 -59
  50. package/test/examples/asciiMaze/asciiMaze.e2e.test.ts +14 -9
  51. package/test/examples/asciiMaze/browser-entry/README.md +196 -0
  52. package/test/examples/asciiMaze/browser-entry/browser-entry.abort.services.ts +95 -0
  53. package/test/examples/asciiMaze/browser-entry/browser-entry.constants.ts +23 -0
  54. package/test/examples/asciiMaze/browser-entry/browser-entry.curriculum.services.ts +115 -0
  55. package/test/examples/asciiMaze/browser-entry/browser-entry.globals.services.ts +106 -0
  56. package/test/examples/asciiMaze/browser-entry/browser-entry.host.services.ts +157 -0
  57. package/test/examples/asciiMaze/browser-entry/browser-entry.services.ts +14 -0
  58. package/test/examples/asciiMaze/browser-entry/browser-entry.ts +129 -0
  59. package/test/examples/asciiMaze/browser-entry/browser-entry.types.ts +120 -0
  60. package/test/examples/asciiMaze/browser-entry/browser-entry.utils.ts +98 -0
  61. package/test/examples/asciiMaze/browser-entry.ts +10 -576
  62. package/test/examples/asciiMaze/dashboardManager/README.md +276 -0
  63. package/test/examples/asciiMaze/dashboardManager/archive/README.md +16 -0
  64. package/test/examples/asciiMaze/dashboardManager/archive/dashboardManager.archive.services.ts +267 -0
  65. package/test/examples/asciiMaze/dashboardManager/dashboardManager.constants.ts +35 -0
  66. package/test/examples/asciiMaze/dashboardManager/dashboardManager.services.ts +103 -0
  67. package/test/examples/asciiMaze/dashboardManager/dashboardManager.ts +181 -0
  68. package/test/examples/asciiMaze/dashboardManager/dashboardManager.types.ts +267 -0
  69. package/test/examples/asciiMaze/dashboardManager/dashboardManager.utils.ts +254 -0
  70. package/test/examples/asciiMaze/dashboardManager/live/README.md +14 -0
  71. package/test/examples/asciiMaze/dashboardManager/live/dashboardManager.live.services.ts +264 -0
  72. package/test/examples/asciiMaze/dashboardManager/telemetry/README.md +47 -0
  73. package/test/examples/asciiMaze/dashboardManager/telemetry/dashboardManager.telemetry.services.ts +513 -0
  74. package/test/examples/asciiMaze/dashboardManager.ts +13 -2335
  75. package/test/examples/asciiMaze/evolutionEngine/README.md +1058 -0
  76. package/test/examples/asciiMaze/evolutionEngine/curriculumPhase.ts +90 -0
  77. package/test/examples/asciiMaze/evolutionEngine/engineState.constants.ts +36 -0
  78. package/test/examples/asciiMaze/evolutionEngine/engineState.ts +58 -513
  79. package/test/examples/asciiMaze/evolutionEngine/engineState.types.ts +212 -0
  80. package/test/examples/asciiMaze/evolutionEngine/engineState.utils.ts +301 -0
  81. package/test/examples/asciiMaze/evolutionEngine/evolutionEngine.types.ts +445 -0
  82. package/test/examples/asciiMaze/evolutionEngine/evolutionLoop.ts +81 -50
  83. package/test/examples/asciiMaze/evolutionEngine/optionsAndSetup.ts +2 -4
  84. package/test/examples/asciiMaze/evolutionEngine/populationDynamics.ts +17 -33
  85. package/test/examples/asciiMaze/evolutionEngine/populationPruning.ts +1 -1
  86. package/test/examples/asciiMaze/evolutionEngine/rngAndTiming.ts +1 -2
  87. package/test/examples/asciiMaze/evolutionEngine/sampling.ts +1 -1
  88. package/test/examples/asciiMaze/evolutionEngine/scratchPools.ts +2 -5
  89. package/test/examples/asciiMaze/evolutionEngine/setupHelpers.ts +30 -37
  90. package/test/examples/asciiMaze/evolutionEngine/telemetryMetrics.ts +16 -58
  91. package/test/examples/asciiMaze/evolutionEngine/trainingWarmStart.ts +2 -2
  92. package/test/examples/asciiMaze/evolutionEngine.ts +55 -55
  93. package/test/examples/asciiMaze/fitness.ts +2 -2
  94. package/test/examples/asciiMaze/fitness.types.ts +65 -0
  95. package/test/examples/asciiMaze/interfaces.ts +64 -1352
  96. package/test/examples/asciiMaze/mazeMovement/README.md +356 -0
  97. package/test/examples/asciiMaze/mazeMovement/finalization/README.md +49 -0
  98. package/test/examples/asciiMaze/mazeMovement/finalization/mazeMovement.finalization.ts +138 -0
  99. package/test/examples/asciiMaze/mazeMovement/mazeMovement.constants.ts +101 -0
  100. package/test/examples/asciiMaze/mazeMovement/mazeMovement.services.ts +230 -0
  101. package/test/examples/asciiMaze/mazeMovement/mazeMovement.ts +299 -0
  102. package/test/examples/asciiMaze/mazeMovement/mazeMovement.types.ts +185 -0
  103. package/test/examples/asciiMaze/mazeMovement/mazeMovement.utils.ts +153 -0
  104. package/test/examples/asciiMaze/mazeMovement/policy/README.md +91 -0
  105. package/test/examples/asciiMaze/mazeMovement/policy/mazeMovement.policy.ts +467 -0
  106. package/test/examples/asciiMaze/mazeMovement/runtime/README.md +95 -0
  107. package/test/examples/asciiMaze/mazeMovement/runtime/mazeMovement.runtime.ts +354 -0
  108. package/test/examples/asciiMaze/mazeMovement/shaping/README.md +124 -0
  109. package/test/examples/asciiMaze/mazeMovement/shaping/mazeMovement.shaping.ts +459 -0
  110. package/test/examples/asciiMaze/mazeMovement.ts +12 -2978
  111. package/test/examples/flappy_bird/Trace-20260309T191949.json +24124 -0
  112. package/test/examples/flappy_bird/browser-entry/README.md +1129 -0
  113. package/test/examples/flappy_bird/browser-entry/browser-entry.host.utils.ts +4 -324
  114. package/test/examples/flappy_bird/browser-entry/browser-entry.network-view.utils.ts +6 -399
  115. package/test/examples/flappy_bird/browser-entry/browser-entry.playback.utils.ts +1 -717
  116. package/test/examples/flappy_bird/browser-entry/browser-entry.spawn.utils.ts +11 -31
  117. package/test/examples/flappy_bird/browser-entry/browser-entry.visualization.utils.ts +15 -893
  118. package/test/examples/flappy_bird/browser-entry/host/README.md +307 -0
  119. package/test/examples/flappy_bird/browser-entry/host/host.resize.service.ts +1 -295
  120. package/test/examples/flappy_bird/browser-entry/host/host.ts +562 -6
  121. package/test/examples/flappy_bird/browser-entry/host/resize/README.md +274 -0
  122. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.constants.ts +31 -0
  123. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.services.ts +360 -0
  124. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.ts +117 -0
  125. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.types.ts +63 -0
  126. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.utils.ts +250 -0
  127. package/test/examples/flappy_bird/browser-entry/network-view/README.md +399 -0
  128. package/test/examples/flappy_bird/browser-entry/network-view/network-view.topology.utils.ts +255 -0
  129. package/test/examples/flappy_bird/browser-entry/network-view/network-view.ts +802 -7
  130. package/test/examples/flappy_bird/browser-entry/playback/README.md +684 -0
  131. package/test/examples/flappy_bird/browser-entry/playback/background/README.md +277 -0
  132. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/README.md +770 -0
  133. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.cache.services.ts +178 -0
  134. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.constants.ts +107 -0
  135. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.geometry.utils.ts +518 -0
  136. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.math.utils.ts +117 -0
  137. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.pulse.utils.ts +233 -0
  138. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.services.ts +211 -0
  139. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.ts +48 -0
  140. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.types.ts +212 -0
  141. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.utils.ts +81 -0
  142. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.cache.services.ts +96 -0
  143. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.constants.ts +62 -0
  144. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.services.ts +244 -0
  145. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.ts +53 -0
  146. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.types.ts +68 -0
  147. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.utils.ts +100 -0
  148. package/test/examples/flappy_bird/browser-entry/playback/frame-render/README.md +310 -0
  149. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.service.ts +92 -0
  150. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.services.ts +272 -0
  151. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.types.ts +39 -0
  152. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.utils.ts +493 -0
  153. package/test/examples/flappy_bird/browser-entry/playback/playback.constants.ts +1 -1
  154. package/test/examples/flappy_bird/browser-entry/playback/playback.frame-render.service.ts +4 -0
  155. package/test/examples/flappy_bird/browser-entry/playback/playback.snapshot.utils.ts +44 -0
  156. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.service.ts +39 -122
  157. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.services.ts +272 -0
  158. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.types.ts +62 -0
  159. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.utils.ts +11 -4
  160. package/test/examples/flappy_bird/browser-entry/playback/playback.ts +409 -8
  161. package/test/examples/flappy_bird/browser-entry/playback/playback.types.ts +4 -12
  162. package/test/examples/flappy_bird/browser-entry/runtime/README.md +235 -0
  163. package/test/examples/flappy_bird/browser-entry/runtime/runtime.evolution-launch.service.ts +45 -0
  164. package/test/examples/flappy_bird/browser-entry/runtime/runtime.lifecycle.service.ts +81 -0
  165. package/test/examples/flappy_bird/browser-entry/runtime/runtime.startup.service.ts +74 -0
  166. package/test/examples/flappy_bird/browser-entry/runtime/runtime.ts +31 -121
  167. package/test/examples/flappy_bird/browser-entry/runtime/runtime.types.ts +36 -0
  168. package/test/examples/flappy_bird/browser-entry/visualization/README.md +557 -0
  169. package/test/examples/flappy_bird/browser-entry/visualization/visualization.constants.ts +110 -0
  170. package/test/examples/flappy_bird/browser-entry/visualization/visualization.draw.service.ts +957 -19
  171. package/test/examples/flappy_bird/browser-entry/visualization/visualization.legend.utils.ts +138 -3
  172. package/test/examples/flappy_bird/browser-entry/visualization/visualization.topology.utils.ts +3 -27
  173. package/test/examples/flappy_bird/browser-entry/visualization/visualization.ts +1 -23
  174. package/test/examples/flappy_bird/browser-entry/worker-channel/README.md +156 -0
  175. package/test/examples/flappy_bird/constants/README.md +1179 -0
  176. package/test/examples/flappy_bird/constants/constants.network-view.ts +24 -0
  177. package/test/examples/flappy_bird/constants/constants.palette.ts +7 -0
  178. package/test/examples/flappy_bird/constants/constants.starfield.ts +78 -3
  179. package/test/examples/flappy_bird/environment/README.md +143 -0
  180. package/test/examples/flappy_bird/environment/environment.observation.utils.ts +1 -19
  181. package/test/examples/flappy_bird/environment/environment.step.service.ts +3 -66
  182. package/test/examples/flappy_bird/evaluation/README.md +130 -0
  183. package/test/examples/flappy_bird/evaluation/evaluation.fitness.utils.ts +1 -1
  184. package/test/examples/flappy_bird/evaluation/evaluation.rollout.service.ts +5 -375
  185. package/test/examples/flappy_bird/evaluation/rollout/README.md +291 -0
  186. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.constants.ts +30 -0
  187. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.service.ts +58 -0
  188. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.services.ts +310 -0
  189. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.types.ts +56 -0
  190. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.utils.ts +368 -0
  191. package/test/examples/flappy_bird/flappy-evolution-worker/README.md +618 -0
  192. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.playback.service.ts +7 -7
  193. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.frame.service.ts +364 -0
  194. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.types.ts +14 -0
  195. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.utils.ts +4 -201
  196. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.ts +184 -345
  197. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.warm-start.service.ts +291 -0
  198. package/test/examples/flappy_bird/flappy.simulation.shared.utils.ts +5 -0
  199. package/test/examples/flappy_bird/simulation-shared/README.md +417 -0
  200. package/test/examples/flappy_bird/simulation-shared/observation/README.md +183 -0
  201. package/test/examples/flappy_bird/simulation-shared/observation/observation.features.utils.ts +301 -0
  202. package/test/examples/flappy_bird/simulation-shared/observation/observation.ts +9 -0
  203. package/test/examples/flappy_bird/simulation-shared/observation/observation.vector.utils.ts +59 -0
  204. package/test/examples/flappy_bird/simulation-shared/simulation-shared.observation.utils.ts +5 -403
  205. package/test/examples/flappy_bird/simulation-shared/simulation-shared.spawn.utils.ts +20 -6
  206. package/test/examples/flappy_bird/{evaluation/evaluation.statistics.utils.ts → simulation-shared/simulation-shared.statistics.utils.ts} +23 -8
  207. package/test/examples/flappy_bird/trainer/README.md +563 -0
  208. package/test/examples/flappy_bird/trainer/evaluation/README.md +199 -0
  209. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.constants.ts +9 -0
  210. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.services.ts +73 -0
  211. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.ts +165 -0
  212. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.types.ts +25 -0
  213. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.utils.ts +161 -0
  214. package/test/examples/flappy_bird/trainer/trainer.evaluation.service.ts +13 -0
  215. package/test/examples/flappy_bird/trainer/trainer.report.service.services.ts +181 -0
  216. package/test/examples/flappy_bird/trainer/trainer.report.service.ts +126 -0
  217. package/test/examples/flappy_bird/trainer/trainer.selection.utils.ts +89 -0
  218. package/test/examples/flappy_bird/trainer/trainer.ts +11 -553
  219. package/test/examples/flappy_bird/browser-entry/browser-entry.utils.ts +0 -12
  220. package/test/examples/flappy_bird/environment/environment.ts +0 -7
  221. package/test/examples/flappy_bird/evaluation/evaluation.ts +0 -7
  222. package/test/examples/flappy_bird/simulation-shared/simulation-shared.ts +0 -15
  223. package/test/examples/flappy_bird/trainer/trainer.statistics.utils.ts +0 -78
@@ -1,406 +1,8 @@
1
- import {
2
- FLAPPY_BIRD_RADIUS_PX,
3
- FLAPPY_BIRD_X_PX,
4
- FLAPPY_FLAP_VELOCITY_PX_PER_FRAME,
5
- FLAPPY_GRAVITY_PX_PER_FRAME2,
6
- FLAPPY_MAX_FALL_SPEED_PX_PER_FRAME,
7
- FLAPPY_MIN_PIPE_RECOVERY_FRAMES,
8
- FLAPPY_PIPE_GAP_PX,
9
- FLAPPY_PIPE_WIDTH_PX,
10
- FLAPPY_WORLD_HEIGHT_PX,
11
- } from '../constants/constants';
12
- import { FLAPPY_SHARED_DEFAULT_NORMALIZATION_EPSILON } from './simulation-shared.constants';
13
- import type {
14
- SharedObservationFeatures,
15
- SharedObservationInput,
16
- SharedPipeLike,
17
- } from './simulation-shared.types';
18
-
19
1
  /**
20
- * Resolves the next two upcoming pipes in front of the bird.
2
+ * Shared observation compatibility façade.
21
3
  *
22
- * @param pipes - Current pipe list.
23
- * @param birdCenterXPx - Bird center x-position.
24
- * @param birdRadiusPx - Bird radius.
25
- * @param pipeWidthPx - Pipe width.
26
- * @returns Tuple of first and second upcoming pipes.
4
+ * The observation implementation now lives under `simulation-shared/observation/`
5
+ * so feature synthesis and vector projection can evolve behind a focused module
6
+ * boundary. This file stays as the stable import path for existing callers.
27
7
  */
28
- export function resolveUpcomingPipes(
29
- pipes: SharedPipeLike[],
30
- birdCenterXPx = FLAPPY_BIRD_X_PX,
31
- birdRadiusPx = FLAPPY_BIRD_RADIUS_PX,
32
- pipeWidthPx = FLAPPY_PIPE_WIDTH_PX,
33
- ): [SharedPipeLike | undefined, SharedPipeLike | undefined] {
34
- const birdFrontX = birdCenterXPx - birdRadiusPx;
35
- const upcomingPipes = pipes.filter(
36
- (pipe) => pipe.xPx + pipeWidthPx >= birdFrontX,
37
- );
38
- return [upcomingPipes[0], upcomingPipes[1]];
39
- }
40
-
41
- /**
42
- * Builds the shared normalized observation feature set consumed by policies.
43
- *
44
- * @param input - Observation input bundle.
45
- * @returns Structured observation features.
46
- */
47
- export function resolveObservationFeatures(
48
- input: SharedObservationInput,
49
- ): SharedObservationFeatures {
50
- /**
51
- * Effective world height used for all vertical normalization.
52
- *
53
- * Why it matters: scaling by a stable height keeps feature magnitudes
54
- * comparable across episodes and prevents value drift when display sizes vary.
55
- */
56
- const worldHeightPx = input.worldHeightPx ?? FLAPPY_WORLD_HEIGHT_PX;
57
- /**
58
- * Maximum downward speed used to normalize velocity-like channels.
59
- *
60
- * Why it matters: velocity channels become dimensionless and bounded in [-1, 1],
61
- * making policy optimization numerically easier.
62
- */
63
- const maxFallSpeedPxPerFrame =
64
- input.maxFallSpeedPxPerFrame ?? FLAPPY_MAX_FALL_SPEED_PX_PER_FRAME;
65
- /** Bird center x-position used to measure forward distances to pipes. */
66
- const birdCenterXPx = input.birdCenterXPx ?? FLAPPY_BIRD_X_PX;
67
- /** Bird collision radius used by upcoming-pipe selection and entry/exit timing. */
68
- const birdRadiusPx = input.birdRadiusPx ?? FLAPPY_BIRD_RADIUS_PX;
69
- /** Pipe width used for distance-to-entry/exit and visibility checks. */
70
- const pipeWidthPx = input.pipeWidthPx ?? FLAPPY_PIPE_WIDTH_PX;
71
- /** Default gap size fallback when no upcoming pipe is available yet. */
72
- const defaultGapSizePx = input.defaultGapSizePx ?? FLAPPY_PIPE_GAP_PX;
73
- /**
74
- * Small denominator guard used in time/urgency calculations.
75
- *
76
- * Why it matters: avoids division by zero and explosive values when
77
- * speed or time-to-event become extremely small.
78
- */
79
- const normalizationEpsilon =
80
- input.normalizationEpsilon ?? FLAPPY_SHARED_DEFAULT_NORMALIZATION_EPSILON;
81
-
82
- /** First and second upcoming pipes used for near-term and lookahead guidance. */
83
- const [nextPipe, secondPipe] = resolveUpcomingPipes(
84
- input.pipes,
85
- birdCenterXPx,
86
- birdRadiusPx,
87
- pipeWidthPx,
88
- );
89
- /** Bird y-position normalized to [0, 1]. */
90
- const normalizedBirdY = clamp01(input.birdYPx / worldHeightPx);
91
- /** Bird vertical velocity normalized to [-1, 1]. */
92
- const normalizedVelocity = clamp(
93
- input.velocityYPxPerFrame / maxFallSpeedPxPerFrame,
94
- -1,
95
- 1,
96
- );
97
-
98
- /** Forward distance from bird to the next pipe corridor (pixels). */
99
- const distanceToNextPipePx = nextPipe
100
- ? nextPipe.xPx + pipeWidthPx - birdCenterXPx
101
- : input.visibleWorldWidthPx;
102
- /** Next-pipe forward distance normalized to [0, 1]. */
103
- const normalizedDistanceToNextPipe = clamp01(
104
- distanceToNextPipePx / input.visibleWorldWidthPx,
105
- );
106
-
107
- /** Next gap center y-position (fallback to mid-world when absent). */
108
- const nextGapCenterYPx = nextPipe?.gapCenterYPx ?? worldHeightPx * 0.5;
109
- /** Half-gap height for clearance and boundary calculations. */
110
- const nextGapHalfPx = (nextPipe?.gapSizePx ?? defaultGapSizePx) * 0.5;
111
- /** Normalized top boundary of the next gap opening. */
112
- const normalizedNextGapTop = clamp01(
113
- (nextGapCenterYPx - nextGapHalfPx) / worldHeightPx,
114
- );
115
- /** Normalized bottom boundary of the next gap opening. */
116
- const normalizedNextGapBottom = clamp01(
117
- (nextGapCenterYPx + nextGapHalfPx) / worldHeightPx,
118
- );
119
- /** Signed bird-to-next-gap-center vertical offset normalized to [-1, 1]. */
120
- const normalizedDeltaToNextGap = clamp(
121
- (input.birdYPx - nextGapCenterYPx) / worldHeightPx,
122
- -1,
123
- 1,
124
- );
125
-
126
- /** Forward distance from bird to the second upcoming pipe (pixels). */
127
- const distanceToSecondPipePx = secondPipe
128
- ? secondPipe.xPx + pipeWidthPx - birdCenterXPx
129
- : input.visibleWorldWidthPx;
130
- /** Second-pipe forward distance normalized to [0, 1]. */
131
- const normalizedDistanceToSecondPipe = clamp01(
132
- distanceToSecondPipePx / input.visibleWorldWidthPx,
133
- );
134
-
135
- /** Second gap center y-position (fallback to next center when absent). */
136
- const secondGapCenterYPx = secondPipe?.gapCenterYPx ?? nextGapCenterYPx;
137
- /** Signed bird-to-second-gap-center vertical offset normalized to [-1, 1]. */
138
- const normalizedDeltaToSecondGap = clamp(
139
- (input.birdYPx - secondGapCenterYPx) / worldHeightPx,
140
- -1,
141
- 1,
142
- );
143
-
144
- /** Estimated frames until reaching the next pipe (continuous-time approximation). */
145
- const estimatedFramesToNextPipe =
146
- distanceToNextPipePx /
147
- Math.max(normalizationEpsilon, input.difficultyProfile.pipeSpeedPxPerFrame);
148
- /** Urgency-like proximity to next pipe in [0, 1], where 1 means imminent. */
149
- const normalizedTimeToNextPipe = clamp01(
150
- 1 -
151
- estimatedFramesToNextPipe / Math.max(1, input.activeSpawnIntervalFrames),
152
- );
153
-
154
- /** Absolute vertical distance from bird to next gap center (pixels). */
155
- const distanceToNextGapCenterPx = Math.abs(input.birdYPx - nextGapCenterYPx);
156
- /** Signed clearance relative to half-gap height, normalized to [-1, 1]. */
157
- const normalizedNextGapClearance = clamp(
158
- (nextGapHalfPx - distanceToNextGapCenterPx) / Math.max(1, nextGapHalfPx),
159
- -1,
160
- 1,
161
- );
162
-
163
- /** Horizontal distance to the gap entry plane (pixels). */
164
- const distanceToGapEntryPx = nextPipe
165
- ? nextPipe.xPx - (birdCenterXPx + birdRadiusPx)
166
- : input.visibleWorldWidthPx;
167
- /** Horizontal distance to the gap exit plane (pixels). */
168
- const distanceToGapExitPx = nextPipe
169
- ? nextPipe.xPx + pipeWidthPx - (birdCenterXPx - birdRadiusPx)
170
- : input.visibleWorldWidthPx;
171
-
172
- /** Frames until gap entry; clamped to non-negative values. */
173
- const framesToGapEntry = Math.max(
174
- 0,
175
- distanceToGapEntryPx /
176
- Math.max(
177
- normalizationEpsilon,
178
- input.difficultyProfile.pipeSpeedPxPerFrame,
179
- ),
180
- );
181
- /**
182
- * Frames until gap exit; never smaller than entry time.
183
- *
184
- * Why it matters: captures tube traversal duration, which is crucial for
185
- * wide-pipe timing and potential two-flap planning.
186
- */
187
- const framesToGapExit = Math.max(
188
- framesToGapEntry,
189
- distanceToGapExitPx /
190
- Math.max(
191
- normalizationEpsilon,
192
- input.difficultyProfile.pipeSpeedPxPerFrame,
193
- ),
194
- );
195
-
196
- /** Frames-to-entry normalized to [0, 1] using spawn-interval scale. */
197
- const normalizedFramesToGapEntry = clamp01(
198
- framesToGapEntry / Math.max(1, input.activeSpawnIntervalFrames),
199
- );
200
- /** Frames-to-exit normalized to [0, 1] using spawn-interval scale. */
201
- const normalizedFramesToGapExit = clamp01(
202
- framesToGapExit / Math.max(1, input.activeSpawnIntervalFrames),
203
- );
204
-
205
- /** Required mean vertical velocity to center at next-pipe contact window. */
206
- const requiredVerticalVelocityToNextGapPxPerFrame = clamp(
207
- (nextGapCenterYPx - input.birdYPx) / Math.max(1, estimatedFramesToNextPipe),
208
- -maxFallSpeedPxPerFrame,
209
- maxFallSpeedPxPerFrame,
210
- );
211
- /** Required velocity-to-next-gap channel normalized to [-1, 1]. */
212
- const normalizedRequiredVerticalVelocityToNextGap = clamp(
213
- requiredVerticalVelocityToNextGapPxPerFrame / maxFallSpeedPxPerFrame,
214
- -1,
215
- 1,
216
- );
217
-
218
- /** Required mean vertical velocity to center precisely at gap entry. */
219
- const requiredVerticalVelocityAtGapEntryPxPerFrame = clamp(
220
- (nextGapCenterYPx - input.birdYPx) / Math.max(1, framesToGapEntry),
221
- -maxFallSpeedPxPerFrame,
222
- maxFallSpeedPxPerFrame,
223
- );
224
- /** Required mean vertical velocity to remain centered by gap exit. */
225
- const requiredVerticalVelocityAtGapExitPxPerFrame = clamp(
226
- (nextGapCenterYPx - input.birdYPx) / Math.max(1, framesToGapExit),
227
- -maxFallSpeedPxPerFrame,
228
- maxFallSpeedPxPerFrame,
229
- );
230
- /** Entry-target velocity normalized to [-1, 1]. */
231
- const normalizedRequiredVerticalVelocityAtGapEntry = clamp(
232
- requiredVerticalVelocityAtGapEntryPxPerFrame / maxFallSpeedPxPerFrame,
233
- -1,
234
- 1,
235
- );
236
- /** Exit-target velocity normalized to [-1, 1]. */
237
- const normalizedRequiredVerticalVelocityAtGapExit = clamp(
238
- requiredVerticalVelocityAtGapExitPxPerFrame / maxFallSpeedPxPerFrame,
239
- -1,
240
- 1,
241
- );
242
-
243
- /**
244
- * Centering urgency in [0, 1]: large offset with little time-to-entry yields
245
- * stronger urgency.
246
- */
247
- const normalizedEntryUrgency = clamp(
248
- Math.abs(normalizedDeltaToNextGap) /
249
- Math.max(normalizationEpsilon, normalizedFramesToGapEntry),
250
- 0,
251
- 1,
252
- );
253
-
254
- /** Predicted entry y-position if no flap occurs before entry. */
255
- const predictedBirdYAtEntryWithoutFlap = resolvePredictedBirdYAtFrames(
256
- input.birdYPx,
257
- input.velocityYPxPerFrame,
258
- framesToGapEntry,
259
- );
260
- /** Predicted entry y-position if one immediate flap occurs before entry. */
261
- const predictedBirdYAtEntryWithOneFlap = resolvePredictedBirdYAtFrames(
262
- input.birdYPx,
263
- FLAPPY_FLAP_VELOCITY_PX_PER_FRAME,
264
- framesToGapEntry,
265
- );
266
- /** Entry centering error (pixels) under no-flap trajectory. */
267
- const noFlapEntryErrorPx = Math.abs(
268
- predictedBirdYAtEntryWithoutFlap - nextGapCenterYPx,
269
- );
270
- /** Entry centering error (pixels) under one-flap trajectory. */
271
- const oneFlapEntryErrorPx = Math.abs(
272
- predictedBirdYAtEntryWithOneFlap - nextGapCenterYPx,
273
- );
274
- /** Best (minimum) entry error among one-step action hypotheses. */
275
- const minimalEntryErrorPx = Math.min(noFlapEntryErrorPx, oneFlapEntryErrorPx);
276
- /** Binary reachability feature: 1 when entry center is recoverable within <=1 flap. */
277
- const normalizedOneFlapReachabilityAtGapEntry =
278
- minimalEntryErrorPx <= nextGapHalfPx ? 1 : 0;
279
-
280
- /** Signed centerline transition from next gap to second gap, normalized to [-1, 1]. */
281
- const normalizedNextToSecondGapTransition = clamp(
282
- (secondGapCenterYPx - nextGapCenterYPx) / worldHeightPx,
283
- -1,
284
- 1,
285
- );
286
-
287
- return {
288
- normalizedBirdY,
289
- normalizedVelocity,
290
- normalizedDistanceToNextPipe,
291
- normalizedDeltaToNextGap,
292
- normalizedNextGapTop,
293
- normalizedNextGapBottom,
294
- normalizedDistanceToSecondPipe,
295
- normalizedDeltaToSecondGap,
296
- normalizedTimeToNextPipe,
297
- normalizedNextGapClearance,
298
- normalizedRequiredVerticalVelocityToNextGap,
299
- normalizedNextToSecondGapTransition,
300
- normalizedFramesToGapEntry,
301
- normalizedFramesToGapExit,
302
- normalizedRequiredVerticalVelocityAtGapEntry,
303
- normalizedRequiredVerticalVelocityAtGapExit,
304
- normalizedEntryUrgency,
305
- normalizedOneFlapReachabilityAtGapEntry,
306
- };
307
- }
308
-
309
- /**
310
- * Converts observation features to the canonical 12-value network input vector.
311
- *
312
- * @param features - Structured feature object.
313
- * @returns Ordered feature vector.
314
- */
315
- export function resolveObservationVectorFromFeatures(
316
- features: SharedObservationFeatures,
317
- ): number[] {
318
- return [
319
- features.normalizedBirdY,
320
- features.normalizedVelocity,
321
- features.normalizedDistanceToNextPipe,
322
- features.normalizedDeltaToNextGap,
323
- features.normalizedNextGapTop,
324
- features.normalizedNextGapBottom,
325
- features.normalizedDistanceToSecondPipe,
326
- features.normalizedDeltaToSecondGap,
327
- features.normalizedTimeToNextPipe,
328
- features.normalizedNextGapClearance,
329
- features.normalizedRequiredVerticalVelocityToNextGap,
330
- features.normalizedNextToSecondGapTransition,
331
- ];
332
- }
333
-
334
- /**
335
- * Resolves the compact core vector used for temporal stacking.
336
- *
337
- * The core intentionally keeps directly observed kinematic/geometric channels
338
- * and drops derived one-step predictors that become redundant once temporal
339
- * context is available.
340
- *
341
- * @param features - Structured observation features.
342
- * @returns Core per-frame vector.
343
- */
344
- export function resolveCoreObservationVectorFromFeatures(
345
- features: SharedObservationFeatures,
346
- ): number[] {
347
- return [
348
- features.normalizedBirdY,
349
- features.normalizedVelocity,
350
- features.normalizedDistanceToNextPipe,
351
- features.normalizedDeltaToNextGap,
352
- features.normalizedNextGapTop,
353
- features.normalizedNextGapBottom,
354
- features.normalizedDistanceToSecondPipe,
355
- features.normalizedDeltaToSecondGap,
356
- features.normalizedNextGapClearance,
357
- features.normalizedRequiredVerticalVelocityToNextGap,
358
- features.normalizedEntryUrgency,
359
- features.normalizedOneFlapReachabilityAtGapEntry,
360
- ];
361
- }
362
-
363
- /**
364
- * Predicts bird y-position after a frame horizon with constant gravity.
365
- *
366
- * This lightweight estimate is used for reachability signals only.
367
- *
368
- * @param startYPx - Current bird y-position.
369
- * @param initialVerticalVelocityPxPerFrame - Initial vertical velocity.
370
- * @param frameHorizon - Predicted horizon in simulation frames.
371
- * @returns Predicted y-position.
372
- */
373
- function resolvePredictedBirdYAtFrames(
374
- startYPx: number,
375
- initialVerticalVelocityPxPerFrame: number,
376
- frameHorizon: number,
377
- ): number {
378
- const safeFrameHorizon = Math.max(0, frameHorizon);
379
- return (
380
- startYPx +
381
- initialVerticalVelocityPxPerFrame * safeFrameHorizon +
382
- 0.5 * FLAPPY_GRAVITY_PX_PER_FRAME2 * safeFrameHorizon * safeFrameHorizon
383
- );
384
- }
385
-
386
- /**
387
- * Clamps a numeric value to the inclusive `[min, max]` interval.
388
- *
389
- * @param value - Candidate value.
390
- * @param min - Inclusive lower bound.
391
- * @param max - Inclusive upper bound.
392
- * @returns Clamped value.
393
- */
394
- function clamp(value: number, min: number, max: number): number {
395
- return Math.min(max, Math.max(min, value));
396
- }
397
-
398
- /**
399
- * Clamps a numeric value to the inclusive `[0, 1]` interval.
400
- *
401
- * @param value - Candidate value.
402
- * @returns Value clamped between 0 and 1.
403
- */
404
- function clamp01(value: number): number {
405
- return clamp(value, 0, 1);
406
- }
8
+ export * from './observation/observation';
@@ -18,12 +18,20 @@ import type {
18
18
  * Samples a random gap center y-position.
19
19
  *
20
20
  * @param rng - Deterministic RNG.
21
+ * @param maximumGapCenterYPx - Optional inclusive upper bound for smaller viewports.
21
22
  * @returns Sampled y-position.
22
23
  */
23
- export function sampleGapCenterY(rng: SharedRngLike): number {
24
+ export function sampleGapCenterY(
25
+ rng: SharedRngLike,
26
+ maximumGapCenterYPx: number = FLAPPY_PIPE_GAP_CENTER_MAX_Y_PX,
27
+ ): number {
28
+ const boundedMaximumGapCenterYPx = Math.max(
29
+ FLAPPY_PIPE_GAP_CENTER_MIN_Y_PX,
30
+ maximumGapCenterYPx,
31
+ );
24
32
  return rng.nextInt(
25
33
  FLAPPY_PIPE_GAP_CENTER_MIN_Y_PX,
26
- FLAPPY_PIPE_GAP_CENTER_MAX_Y_PX,
34
+ boundedMaximumGapCenterYPx,
27
35
  );
28
36
  }
29
37
 
@@ -32,25 +40,31 @@ export function sampleGapCenterY(rng: SharedRngLike): number {
32
40
  *
33
41
  * @param previousGapCenterYPx - Previous spawn gap center.
34
42
  * @param rng - Deterministic RNG.
43
+ * @param maximumGapCenterYPx - Optional inclusive upper bound for smaller viewports.
35
44
  * @returns Next gap center y-position.
36
45
  */
37
46
  export function resolveNextSpawnGapCenterY(
38
47
  previousGapCenterYPx: number,
39
48
  rng: SharedRngLike,
49
+ maximumGapCenterYPx: number = FLAPPY_PIPE_GAP_CENTER_MAX_Y_PX,
40
50
  ): number {
41
- const sampledGapCenterYPx = sampleGapCenterY(rng);
51
+ const boundedMaximumGapCenterYPx = Math.max(
52
+ FLAPPY_PIPE_GAP_CENTER_MIN_Y_PX,
53
+ maximumGapCenterYPx,
54
+ );
55
+ const sampledGapCenterYPx = sampleGapCenterY(rng, boundedMaximumGapCenterYPx);
42
56
  const minimumGapCenterYPx = Math.max(
43
57
  FLAPPY_PIPE_GAP_CENTER_MIN_Y_PX,
44
58
  previousGapCenterYPx - FLAPPY_PIPE_GAP_CENTER_MAX_DELTA_PX,
45
59
  );
46
- const maximumGapCenterYPx = Math.min(
47
- FLAPPY_PIPE_GAP_CENTER_MAX_Y_PX,
60
+ const clampedMaximumGapCenterYPx = Math.min(
61
+ boundedMaximumGapCenterYPx,
48
62
  previousGapCenterYPx + FLAPPY_PIPE_GAP_CENTER_MAX_DELTA_PX,
49
63
  );
50
64
  return clampValue(
51
65
  sampledGapCenterYPx,
52
66
  minimumGapCenterYPx,
53
- maximumGapCenterYPx,
67
+ clampedMaximumGapCenterYPx,
54
68
  );
55
69
  }
56
70
 
@@ -1,4 +1,4 @@
1
- import { clampValue } from '../flappy.simulation.shared.utils';
1
+ import { clampValue } from './simulation-shared.math.utils';
2
2
 
3
3
  /**
4
4
  * Computes arithmetic mean for numeric samples.
@@ -26,11 +26,13 @@ export function computePopulationStandardDeviation(
26
26
  meanValue: number,
27
27
  ): number {
28
28
  if (values.length === 0) return 0;
29
+
29
30
  const variance =
30
31
  values.reduce((accumulator, value) => {
31
- const delta = value - meanValue;
32
- return accumulator + delta * delta;
32
+ const deltaFromMean = value - meanValue;
33
+ return accumulator + deltaFromMean * deltaFromMean;
33
34
  }, 0) / values.length;
35
+
34
36
  return Math.sqrt(Math.max(0, variance));
35
37
  }
36
38
 
@@ -46,16 +48,29 @@ export function computePercentile(
46
48
  percentile: number,
47
49
  ): number {
48
50
  if (values.length === 0) return Number.NaN;
49
- const sortedValues = values.toSorted(
50
- (leftValue, rightValue) => leftValue - rightValue,
51
- );
51
+
52
+ const sortedValues = values.toSorted(compareNumbersAscending);
52
53
  const clampedPercentile = clampValue(percentile, 0, 1);
53
54
  const rawIndex = clampedPercentile * (sortedValues.length - 1);
54
55
  const lowerIndex = Math.floor(rawIndex);
55
56
  const upperIndex = Math.ceil(rawIndex);
56
- const interpolation = rawIndex - lowerIndex;
57
+ const interpolationWeight = rawIndex - lowerIndex;
57
58
 
58
59
  const lowerValue = sortedValues[lowerIndex] ?? sortedValues[0] ?? Number.NaN;
59
60
  const upperValue = sortedValues[upperIndex] ?? lowerValue;
60
- return lowerValue + (upperValue - lowerValue) * interpolation;
61
+ return lowerValue + (upperValue - lowerValue) * interpolationWeight;
62
+ }
63
+
64
+ /**
65
+ * Compares two numeric values in ascending order.
66
+ *
67
+ * @param leftValue - Left numeric value.
68
+ * @param rightValue - Right numeric value.
69
+ * @returns Comparator delta for `Array.prototype.toSorted`.
70
+ */
71
+ function compareNumbersAscending(
72
+ leftValue: number,
73
+ rightValue: number,
74
+ ): number {
75
+ return leftValue - rightValue;
61
76
  }