@reicek/neataptic-ts 0.1.21 → 0.1.23

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 (361) hide show
  1. package/.github/agents/boundary-mapper.agent.md +31 -0
  2. package/.github/agents/docs-scout.agent.md +29 -0
  3. package/.github/agents/plan-scout.agent.md +31 -0
  4. package/.github/agents/solid-split.agent.md +143 -0
  5. package/.github/copilot-instructions.md +119 -0
  6. package/.github/skills/solid-split-playbook/SKILL.md +220 -0
  7. package/.github/skills/solid-split-playbook/assets/docs-checklist.md +34 -0
  8. package/.github/skills/solid-split-playbook/assets/split-plan-template.md +48 -0
  9. package/.github/skills/solid-split-playbook/assets/split-workflow-checklist.md +51 -0
  10. package/.github/skills/trace-analyzer-extension/SKILL.md +63 -0
  11. package/.github/skills/trace-analyzer-extension/assets/extension-checklist.md +24 -0
  12. package/.github/skills/trace-analyzer-extension/references/analyzer-extension-workflow.md +101 -0
  13. package/.github/skills/trace-audit-reporting/SKILL.md +96 -0
  14. package/.github/skills/trace-audit-reporting/assets/performance-report-template.md +123 -0
  15. package/.github/skills/trace-audit-reporting/references/trace-analysis-workflow.md +132 -0
  16. package/package.json +7 -3
  17. package/plans/ES2023 migration +13 -8
  18. package/plans/Evolution_Training_Interoperability_Contracts.md +1 -1
  19. package/plans/Flappy_Bird_Folder_Documentation_Pass.md +53 -0
  20. package/plans/Flappy_Evolution_Worker_Documentation_Pass.md +58 -0
  21. package/plans/Interactive_Examples_and_Learning_Path.md +10 -2
  22. package/plans/Memory_Optimization.md +3 -3
  23. package/plans/README.md +63 -0
  24. package/plans/Roadmap.md +15 -3
  25. package/plans/asciiMaze_SOLID_split.done.md +130 -0
  26. package/plans/flappy_bird_SOLID_split.done.md +67 -0
  27. package/scripts/analyze-trace.ts +590 -0
  28. package/scripts/assets/theme.css +221 -34
  29. package/scripts/copy-examples.mjs +9 -5
  30. package/scripts/export-onnx.mjs +3 -3
  31. package/scripts/generate-bench-tables.mjs +10 -10
  32. package/scripts/generate-bench-tables.ts +10 -10
  33. package/scripts/generate-docs.ts +1415 -449
  34. package/scripts/render-docs-html.ts +15 -8
  35. package/src/README.md +127 -222
  36. package/src/architecture/README.md +117 -184
  37. package/src/architecture/architect.ts +6 -0
  38. package/src/architecture/layer/README.md +38 -38
  39. package/src/architecture/network/README.md +49 -31
  40. package/src/architecture/network/activate/README.md +77 -77
  41. package/src/architecture/network/connect/README.md +15 -13
  42. package/src/architecture/network/deterministic/README.md +7 -7
  43. package/src/architecture/network/evolve/README.md +44 -44
  44. package/src/architecture/network/gating/README.md +20 -20
  45. package/src/architecture/network/genetic/README.md +51 -51
  46. package/src/architecture/network/mutate/README.md +97 -97
  47. package/src/architecture/network/network.types.ts +39 -0
  48. package/src/architecture/network/onnx/README.md +264 -264
  49. package/src/architecture/network/prune/README.md +39 -39
  50. package/src/architecture/network/remove/README.md +26 -26
  51. package/src/architecture/network/serialize/README.md +56 -56
  52. package/src/architecture/network/serialize/network.serialize.json.utils.ts +1 -0
  53. package/src/architecture/network/serialize/network.serialize.utils.ts +6 -1
  54. package/src/architecture/network/serialize/network.serialize.utils.types.ts +1 -1
  55. package/src/architecture/network/slab/README.md +61 -61
  56. package/src/architecture/network/standalone/README.md +24 -24
  57. package/src/architecture/network/stats/README.md +9 -9
  58. package/src/architecture/network/topology/README.md +46 -46
  59. package/src/architecture/network/training/README.md +21 -21
  60. package/src/architecture/network.ts +114 -10
  61. package/src/methods/README.md +9 -87
  62. package/src/multithreading/README.md +8 -77
  63. package/src/multithreading/workers/README.md +2 -2
  64. package/src/multithreading/workers/browser/README.md +0 -6
  65. package/src/multithreading/workers/node/README.md +0 -3
  66. package/src/neat/README.md +623 -568
  67. package/src/neat/neat.evolve.population.utils.ts +29 -5
  68. package/src/neat/neat.helpers.ts +16 -0
  69. package/src/neat/neat.topology-intent.utils.ts +160 -0
  70. package/src/utils/README.md +18 -18
  71. package/test/examples/asciiMaze/README.md +59 -59
  72. package/test/examples/asciiMaze/asciiMaze.e2e.test.ts +14 -9
  73. package/test/examples/asciiMaze/browser-entry/README.md +196 -0
  74. package/test/examples/asciiMaze/browser-entry/browser-entry.abort.services.ts +95 -0
  75. package/test/examples/asciiMaze/browser-entry/browser-entry.constants.ts +23 -0
  76. package/test/examples/asciiMaze/browser-entry/browser-entry.curriculum.services.ts +115 -0
  77. package/test/examples/asciiMaze/browser-entry/browser-entry.globals.services.ts +106 -0
  78. package/test/examples/asciiMaze/browser-entry/browser-entry.host.services.ts +157 -0
  79. package/test/examples/asciiMaze/browser-entry/browser-entry.services.ts +14 -0
  80. package/test/examples/asciiMaze/browser-entry/browser-entry.ts +129 -0
  81. package/test/examples/asciiMaze/browser-entry/browser-entry.types.ts +120 -0
  82. package/test/examples/asciiMaze/browser-entry/browser-entry.utils.ts +98 -0
  83. package/test/examples/asciiMaze/browser-entry.ts +10 -576
  84. package/test/examples/asciiMaze/dashboardManager/README.md +276 -0
  85. package/test/examples/asciiMaze/dashboardManager/archive/README.md +16 -0
  86. package/test/examples/asciiMaze/dashboardManager/archive/dashboardManager.archive.services.ts +267 -0
  87. package/test/examples/asciiMaze/dashboardManager/dashboardManager.constants.ts +35 -0
  88. package/test/examples/asciiMaze/dashboardManager/dashboardManager.services.ts +103 -0
  89. package/test/examples/asciiMaze/dashboardManager/dashboardManager.ts +181 -0
  90. package/test/examples/asciiMaze/dashboardManager/dashboardManager.types.ts +267 -0
  91. package/test/examples/asciiMaze/dashboardManager/dashboardManager.utils.ts +254 -0
  92. package/test/examples/asciiMaze/dashboardManager/live/README.md +14 -0
  93. package/test/examples/asciiMaze/dashboardManager/live/dashboardManager.live.services.ts +264 -0
  94. package/test/examples/asciiMaze/dashboardManager/telemetry/README.md +47 -0
  95. package/test/examples/asciiMaze/dashboardManager/telemetry/dashboardManager.telemetry.services.ts +513 -0
  96. package/test/examples/asciiMaze/dashboardManager.ts +13 -2335
  97. package/test/examples/asciiMaze/evolutionEngine/README.md +1058 -0
  98. package/test/examples/asciiMaze/evolutionEngine/curriculumPhase.ts +90 -0
  99. package/test/examples/asciiMaze/evolutionEngine/engineState.constants.ts +36 -0
  100. package/test/examples/asciiMaze/evolutionEngine/engineState.ts +58 -513
  101. package/test/examples/asciiMaze/evolutionEngine/engineState.types.ts +212 -0
  102. package/test/examples/asciiMaze/evolutionEngine/engineState.utils.ts +301 -0
  103. package/test/examples/asciiMaze/evolutionEngine/evolutionEngine.types.ts +445 -0
  104. package/test/examples/asciiMaze/evolutionEngine/evolutionLoop.ts +81 -50
  105. package/test/examples/asciiMaze/evolutionEngine/optionsAndSetup.ts +2 -4
  106. package/test/examples/asciiMaze/evolutionEngine/populationDynamics.ts +17 -33
  107. package/test/examples/asciiMaze/evolutionEngine/populationPruning.ts +1 -1
  108. package/test/examples/asciiMaze/evolutionEngine/rngAndTiming.ts +1 -2
  109. package/test/examples/asciiMaze/evolutionEngine/sampling.ts +1 -1
  110. package/test/examples/asciiMaze/evolutionEngine/scratchPools.ts +2 -5
  111. package/test/examples/asciiMaze/evolutionEngine/setupHelpers.ts +30 -37
  112. package/test/examples/asciiMaze/evolutionEngine/telemetryMetrics.ts +16 -58
  113. package/test/examples/asciiMaze/evolutionEngine/trainingWarmStart.ts +2 -2
  114. package/test/examples/asciiMaze/evolutionEngine.ts +55 -55
  115. package/test/examples/asciiMaze/fitness.ts +2 -2
  116. package/test/examples/asciiMaze/fitness.types.ts +65 -0
  117. package/test/examples/asciiMaze/interfaces.ts +64 -1352
  118. package/test/examples/asciiMaze/mazeMovement/README.md +356 -0
  119. package/test/examples/asciiMaze/mazeMovement/finalization/README.md +49 -0
  120. package/test/examples/asciiMaze/mazeMovement/finalization/mazeMovement.finalization.ts +138 -0
  121. package/test/examples/asciiMaze/mazeMovement/mazeMovement.constants.ts +101 -0
  122. package/test/examples/asciiMaze/mazeMovement/mazeMovement.services.ts +230 -0
  123. package/test/examples/asciiMaze/mazeMovement/mazeMovement.ts +299 -0
  124. package/test/examples/asciiMaze/mazeMovement/mazeMovement.types.ts +185 -0
  125. package/test/examples/asciiMaze/mazeMovement/mazeMovement.utils.ts +153 -0
  126. package/test/examples/asciiMaze/mazeMovement/policy/README.md +91 -0
  127. package/test/examples/asciiMaze/mazeMovement/policy/mazeMovement.policy.ts +467 -0
  128. package/test/examples/asciiMaze/mazeMovement/runtime/README.md +95 -0
  129. package/test/examples/asciiMaze/mazeMovement/runtime/mazeMovement.runtime.ts +354 -0
  130. package/test/examples/asciiMaze/mazeMovement/shaping/README.md +124 -0
  131. package/test/examples/asciiMaze/mazeMovement/shaping/mazeMovement.shaping.ts +459 -0
  132. package/test/examples/asciiMaze/mazeMovement.ts +12 -2978
  133. package/test/examples/flappy_bird/README.md +193 -88
  134. package/test/examples/flappy_bird/browser-entry/README.md +1441 -0
  135. package/test/examples/flappy_bird/browser-entry/browser-entry.host.utils.ts +4 -324
  136. package/test/examples/flappy_bird/browser-entry/browser-entry.network-view.utils.ts +9 -396
  137. package/test/examples/flappy_bird/browser-entry/browser-entry.playback.utils.ts +6 -714
  138. package/test/examples/flappy_bird/browser-entry/browser-entry.render.types.ts +26 -3
  139. package/test/examples/flappy_bird/browser-entry/browser-entry.runtime.types.ts +16 -1
  140. package/test/examples/flappy_bird/browser-entry/browser-entry.simulation.types.ts +39 -5
  141. package/test/examples/flappy_bird/browser-entry/browser-entry.spawn.utils.ts +11 -31
  142. package/test/examples/flappy_bird/browser-entry/browser-entry.stats.types.ts +32 -4
  143. package/test/examples/flappy_bird/browser-entry/browser-entry.ts +11 -0
  144. package/test/examples/flappy_bird/browser-entry/browser-entry.types.ts +8 -0
  145. package/test/examples/flappy_bird/browser-entry/browser-entry.visualization.types.ts +50 -7
  146. package/test/examples/flappy_bird/browser-entry/browser-entry.visualization.utils.ts +21 -893
  147. package/test/examples/flappy_bird/browser-entry/browser-entry.worker.types.ts +91 -10
  148. package/test/examples/flappy_bird/browser-entry/host/README.md +318 -0
  149. package/test/examples/flappy_bird/browser-entry/host/host.canvas.service.ts +16 -0
  150. package/test/examples/flappy_bird/browser-entry/host/host.constants.ts +20 -0
  151. package/test/examples/flappy_bird/browser-entry/host/host.dom.service.ts +10 -0
  152. package/test/examples/flappy_bird/browser-entry/host/host.resize.service.ts +1 -295
  153. package/test/examples/flappy_bird/browser-entry/host/host.stats.service.ts +14 -0
  154. package/test/examples/flappy_bird/browser-entry/host/host.ts +592 -6
  155. package/test/examples/flappy_bird/browser-entry/host/host.types.ts +13 -0
  156. package/test/examples/flappy_bird/browser-entry/host/resize/README.md +309 -0
  157. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.constants.ts +47 -0
  158. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.services.ts +392 -0
  159. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.ts +132 -0
  160. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.types.ts +92 -0
  161. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.utils.ts +272 -0
  162. package/test/examples/flappy_bird/browser-entry/network-view/README.md +389 -0
  163. package/test/examples/flappy_bird/browser-entry/network-view/network-view.draw.service.ts +13 -0
  164. package/test/examples/flappy_bird/browser-entry/network-view/network-view.labels.utils.ts +12 -0
  165. package/test/examples/flappy_bird/browser-entry/network-view/network-view.layout.utils.ts +14 -0
  166. package/test/examples/flappy_bird/browser-entry/network-view/network-view.topology.utils.ts +267 -0
  167. package/test/examples/flappy_bird/browser-entry/network-view/network-view.ts +823 -7
  168. package/test/examples/flappy_bird/browser-entry/network-view/network-view.types.ts +11 -0
  169. package/test/examples/flappy_bird/browser-entry/playback/README.md +845 -0
  170. package/test/examples/flappy_bird/browser-entry/playback/background/README.md +355 -0
  171. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/README.md +1068 -0
  172. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.batch.services.ts +64 -0
  173. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.cache.services.ts +207 -0
  174. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.constants.ts +197 -0
  175. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.geometry.batch.utils.ts +114 -0
  176. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.geometry.layout.utils.test.ts +96 -0
  177. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.geometry.layout.utils.ts +204 -0
  178. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.geometry.services.ts +49 -0
  179. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.geometry.utils.ts +313 -0
  180. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.layer.services.ts +81 -0
  181. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.math.utils.test.ts +33 -0
  182. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.math.utils.ts +201 -0
  183. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.pulse.selection.utils.ts +171 -0
  184. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.pulse.timing.utils.ts +124 -0
  185. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.pulse.utils.test.ts +279 -0
  186. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.pulse.utils.ts +132 -0
  187. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.scene.services.ts +26 -0
  188. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.services.ts +65 -0
  189. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.ts +48 -0
  190. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.types.ts +342 -0
  191. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.utils.ts +10 -0
  192. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.cache.services.ts +96 -0
  193. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.constants.ts +127 -0
  194. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.draw.services.ts +184 -0
  195. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.scene.services.ts +64 -0
  196. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.services.ts +6 -0
  197. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.ts +53 -0
  198. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.types.ts +105 -0
  199. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.utils.ts +100 -0
  200. package/test/examples/flappy_bird/browser-entry/playback/frame-render/README.md +541 -0
  201. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.bird.utils.ts +180 -0
  202. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.canvas.services.ts +77 -0
  203. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.entity.services.ts +167 -0
  204. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.scene.services.ts +57 -0
  205. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.service.test.ts +176 -0
  206. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.service.ts +113 -0
  207. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.services.ts +35 -0
  208. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.trail.utils.ts +248 -0
  209. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.types.ts +103 -0
  210. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.utils.ts +11 -0
  211. package/test/examples/flappy_bird/browser-entry/playback/playback.constants.ts +1 -1
  212. package/test/examples/flappy_bird/browser-entry/playback/playback.frame-render.service.ts +10 -0
  213. package/test/examples/flappy_bird/browser-entry/playback/playback.iteration.services.ts +192 -0
  214. package/test/examples/flappy_bird/browser-entry/playback/playback.loop.service.ts +12 -0
  215. package/test/examples/flappy_bird/browser-entry/playback/playback.orchestration.types.ts +78 -0
  216. package/test/examples/flappy_bird/browser-entry/playback/playback.render.pipe-outline.service.ts +128 -0
  217. package/test/examples/flappy_bird/browser-entry/playback/playback.render.service.ts +1 -116
  218. package/test/examples/flappy_bird/browser-entry/playback/playback.session.services.ts +184 -0
  219. package/test/examples/flappy_bird/browser-entry/playback/playback.snapshot.utils.test.ts +121 -0
  220. package/test/examples/flappy_bird/browser-entry/playback/playback.snapshot.utils.ts +8 -0
  221. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.layer.services.ts +36 -0
  222. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.service.ts +11 -128
  223. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.services.ts +268 -0
  224. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.types.ts +91 -0
  225. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.utils.ts +11 -4
  226. package/test/examples/flappy_bird/browser-entry/playback/playback.trail.utils.ts +9 -86
  227. package/test/examples/flappy_bird/browser-entry/playback/playback.ts +75 -7
  228. package/test/examples/flappy_bird/browser-entry/playback/playback.types.ts +12 -9
  229. package/test/examples/flappy_bird/browser-entry/playback/playback.worker-channel.utils.ts +11 -123
  230. package/test/examples/flappy_bird/browser-entry/playback/snapshot/README.md +55 -0
  231. package/test/examples/flappy_bird/browser-entry/playback/snapshot/playback.snapshot.services.ts +103 -0
  232. package/test/examples/flappy_bird/browser-entry/playback/snapshot/playback.snapshot.summary.utils.test.ts +45 -0
  233. package/test/examples/flappy_bird/browser-entry/playback/snapshot/playback.snapshot.summary.utils.ts +28 -0
  234. package/test/examples/flappy_bird/browser-entry/playback/trail/README.md +95 -0
  235. package/test/examples/flappy_bird/browser-entry/playback/trail/playback.trail.history.services.test.ts +35 -0
  236. package/test/examples/flappy_bird/browser-entry/playback/trail/playback.trail.history.services.ts +64 -0
  237. package/test/examples/flappy_bird/browser-entry/playback/trail/playback.trail.opacity.utils.test.ts +37 -0
  238. package/test/examples/flappy_bird/browser-entry/playback/trail/playback.trail.opacity.utils.ts +74 -0
  239. package/test/examples/flappy_bird/browser-entry/playback/worker-channel/README.md +71 -0
  240. package/test/examples/flappy_bird/browser-entry/playback/worker-channel/playback.worker-channel.request.services.ts +45 -0
  241. package/test/examples/flappy_bird/browser-entry/playback/worker-channel/playback.worker-channel.summary.services.ts +74 -0
  242. package/test/examples/flappy_bird/browser-entry/playback/worker-channel/playback.worker-channel.types.ts +53 -0
  243. package/test/examples/flappy_bird/browser-entry/runtime/README.md +304 -0
  244. package/test/examples/flappy_bird/browser-entry/runtime/runtime.browser-globals.service.ts +15 -0
  245. package/test/examples/flappy_bird/browser-entry/runtime/runtime.errors.ts +17 -0
  246. package/test/examples/flappy_bird/browser-entry/runtime/runtime.evolution-launch.service.ts +56 -0
  247. package/test/examples/flappy_bird/browser-entry/runtime/runtime.evolution-loop.service.ts +19 -0
  248. package/test/examples/flappy_bird/browser-entry/runtime/runtime.lifecycle.service.ts +96 -0
  249. package/test/examples/flappy_bird/browser-entry/runtime/runtime.startup.service.ts +92 -0
  250. package/test/examples/flappy_bird/browser-entry/runtime/runtime.telemetry.service.ts +24 -0
  251. package/test/examples/flappy_bird/browser-entry/runtime/runtime.ts +31 -121
  252. package/test/examples/flappy_bird/browser-entry/runtime/runtime.types.ts +65 -0
  253. package/test/examples/flappy_bird/browser-entry/visualization/README.md +568 -0
  254. package/test/examples/flappy_bird/browser-entry/visualization/visualization.colors.utils.ts +26 -0
  255. package/test/examples/flappy_bird/browser-entry/visualization/visualization.constants.ts +110 -0
  256. package/test/examples/flappy_bird/browser-entry/visualization/visualization.draw.service.ts +979 -19
  257. package/test/examples/flappy_bird/browser-entry/visualization/visualization.legend.utils.ts +157 -3
  258. package/test/examples/flappy_bird/browser-entry/visualization/visualization.topology.utils.ts +13 -27
  259. package/test/examples/flappy_bird/browser-entry/visualization/visualization.ts +7 -20
  260. package/test/examples/flappy_bird/browser-entry/visualization/visualization.types.ts +14 -0
  261. package/test/examples/flappy_bird/browser-entry/worker-channel/README.md +238 -0
  262. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.errors.ts +11 -0
  263. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.generation.service.ts +12 -0
  264. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.playback.service.test.ts +143 -0
  265. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.playback.service.ts +140 -14
  266. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.request.service.ts +27 -0
  267. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.ts +8 -0
  268. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.types.ts +23 -0
  269. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.url.service.ts +5 -0
  270. package/test/examples/flappy_bird/constants/README.md +1163 -0
  271. package/test/examples/flappy_bird/constants/constants.birds.ts +16 -38
  272. package/test/examples/flappy_bird/constants/constants.difficulty.ts +21 -0
  273. package/test/examples/flappy_bird/constants/constants.network-view.ts +24 -0
  274. package/test/examples/flappy_bird/constants/constants.network.ts +1 -1
  275. package/test/examples/flappy_bird/constants/constants.observation.ts +7 -0
  276. package/test/examples/flappy_bird/constants/constants.palette.ts +9 -2
  277. package/test/examples/flappy_bird/constants/constants.physics.ts +9 -0
  278. package/test/examples/flappy_bird/constants/constants.pipe-render.ts +3 -0
  279. package/test/examples/flappy_bird/constants/constants.pipes.ts +22 -3
  280. package/test/examples/flappy_bird/constants/constants.runtime.ts +28 -4
  281. package/test/examples/flappy_bird/constants/constants.starfield.ts +78 -3
  282. package/test/examples/flappy_bird/constants/constants.ts +6 -0
  283. package/test/examples/flappy_bird/environment/README.md +182 -0
  284. package/test/examples/flappy_bird/environment/environment.collision.utils.ts +7 -0
  285. package/test/examples/flappy_bird/environment/environment.constants.ts +16 -3
  286. package/test/examples/flappy_bird/environment/environment.observation.utils.ts +12 -19
  287. package/test/examples/flappy_bird/environment/environment.state.service.ts +10 -0
  288. package/test/examples/flappy_bird/environment/environment.step.service.ts +15 -66
  289. package/test/examples/flappy_bird/environment/environment.types.ts +14 -0
  290. package/test/examples/flappy_bird/evaluation/README.md +155 -0
  291. package/test/examples/flappy_bird/evaluation/evaluation.constants.ts +23 -4
  292. package/test/examples/flappy_bird/evaluation/evaluation.fitness.utils.ts +16 -1
  293. package/test/examples/flappy_bird/evaluation/evaluation.rollout.service.ts +7 -374
  294. package/test/examples/flappy_bird/evaluation/evaluation.seed.utils.ts +4 -0
  295. package/test/examples/flappy_bird/evaluation/evaluation.types.ts +18 -2
  296. package/test/examples/flappy_bird/evaluation/rollout/README.md +355 -0
  297. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.constants.ts +38 -0
  298. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.service.ts +71 -0
  299. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.services.ts +338 -0
  300. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.types.ts +69 -0
  301. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.utils.ts +399 -0
  302. package/test/examples/flappy_bird/flappy-evolution-worker/README.md +845 -0
  303. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.constants.ts +49 -7
  304. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.errors.ts +34 -3
  305. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.evolution.service.ts +22 -0
  306. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.playback.service.ts +62 -26
  307. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.protocol.service.ts +27 -1
  308. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.runtime.service.ts +23 -0
  309. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.frame.service.ts +378 -0
  310. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.types.ts +22 -0
  311. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.utils.ts +20 -203
  312. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.snapshot.utils.test.ts +94 -0
  313. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.snapshot.utils.ts +78 -13
  314. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.ts +235 -344
  315. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.types.ts +170 -22
  316. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.warm-start.service.ts +314 -0
  317. package/test/examples/flappy_bird/flappy.simulation.shared.utils.ts +17 -0
  318. package/test/examples/flappy_bird/flappyEnvironment.ts +21 -0
  319. package/test/examples/flappy_bird/flappyEvaluation.ts +12 -0
  320. package/test/examples/flappy_bird/flappyEvolution.worker.ts +7 -0
  321. package/test/examples/flappy_bird/index.ts +8 -2
  322. package/test/examples/flappy_bird/rng.ts +10 -0
  323. package/test/examples/flappy_bird/simulation-shared/README.md +518 -0
  324. package/test/examples/flappy_bird/simulation-shared/observation/README.md +255 -0
  325. package/test/examples/flappy_bird/simulation-shared/observation/observation.features.utils.ts +339 -0
  326. package/test/examples/flappy_bird/simulation-shared/observation/observation.ts +19 -0
  327. package/test/examples/flappy_bird/simulation-shared/observation/observation.vector.utils.ts +81 -0
  328. package/test/examples/flappy_bird/simulation-shared/simulation-shared.constants.ts +3 -0
  329. package/test/examples/flappy_bird/simulation-shared/simulation-shared.control.utils.ts +6 -0
  330. package/test/examples/flappy_bird/simulation-shared/simulation-shared.difficulty.utils.ts +9 -0
  331. package/test/examples/flappy_bird/simulation-shared/simulation-shared.errors.ts +10 -1
  332. package/test/examples/flappy_bird/simulation-shared/simulation-shared.memory.utils.ts +18 -0
  333. package/test/examples/flappy_bird/simulation-shared/simulation-shared.observation.utils.ts +7 -402
  334. package/test/examples/flappy_bird/simulation-shared/simulation-shared.spawn.utils.ts +36 -6
  335. package/test/examples/flappy_bird/{evaluation/evaluation.statistics.utils.ts → simulation-shared/simulation-shared.statistics.utils.ts} +30 -9
  336. package/test/examples/flappy_bird/simulation-shared/simulation-shared.types.ts +38 -5
  337. package/test/examples/flappy_bird/trainFlappyBird.ts +13 -0
  338. package/test/examples/flappy_bird/trainer/README.md +676 -0
  339. package/test/examples/flappy_bird/trainer/evaluation/README.md +253 -0
  340. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.constants.ts +15 -0
  341. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.services.ts +86 -0
  342. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.ts +187 -0
  343. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.types.ts +32 -0
  344. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.utils.ts +182 -0
  345. package/test/examples/flappy_bird/trainer/trainer.evaluation.service.ts +13 -0
  346. package/test/examples/flappy_bird/trainer/trainer.fitness.service.ts +23 -1
  347. package/test/examples/flappy_bird/trainer/trainer.loop.service.ts +17 -1
  348. package/test/examples/flappy_bird/trainer/trainer.report.service.services.ts +181 -0
  349. package/test/examples/flappy_bird/trainer/trainer.report.service.ts +136 -0
  350. package/test/examples/flappy_bird/trainer/trainer.selection.utils.ts +89 -0
  351. package/test/examples/flappy_bird/trainer/trainer.setup.service.ts +22 -0
  352. package/test/examples/flappy_bird/trainer/trainer.signals.service.ts +8 -0
  353. package/test/examples/flappy_bird/trainer/trainer.ts +38 -553
  354. package/test/examples/flappy_bird/trainer/trainer.types.ts +44 -7
  355. package/test/neat/neat.topology-intent.test.ts +129 -0
  356. package/test/network/network.topology-intent.test.ts +44 -0
  357. package/test/examples/flappy_bird/browser-entry/browser-entry.utils.ts +0 -12
  358. package/test/examples/flappy_bird/environment/environment.ts +0 -7
  359. package/test/examples/flappy_bird/evaluation/evaluation.ts +0 -7
  360. package/test/examples/flappy_bird/simulation-shared/simulation-shared.ts +0 -15
  361. package/test/examples/flappy_bird/trainer/trainer.statistics.utils.ts +0 -78
@@ -0,0 +1,64 @@
1
+ import type { PlaybackGroundGridSegmentBatch } from './playback.background.ground-grid.types';
2
+
3
+ /**
4
+ * Draws one ordered collection of neon segment batches.
5
+ *
6
+ * @param context - Canvas 2D drawing context.
7
+ * @param batches - Ordered line-segment batches to render.
8
+ * @param lineColor - Core neon stroke color.
9
+ * @returns Nothing.
10
+ */
11
+ export function drawGroundGridSegmentBatches(
12
+ context: CanvasRenderingContext2D,
13
+ batches: readonly PlaybackGroundGridSegmentBatch[],
14
+ lineColor: string,
15
+ ): void {
16
+ context.save();
17
+ context.strokeStyle = lineColor;
18
+
19
+ for (const batch of batches) {
20
+ drawGroundGridSegmentBatch(context, batch);
21
+ }
22
+
23
+ context.restore();
24
+ }
25
+
26
+ /**
27
+ * Draws one batch of neon line segments that share one render style.
28
+ *
29
+ * @param context - Canvas 2D drawing context.
30
+ * @param batch - Ordered line-segment batch that shares one render style.
31
+ * @returns Nothing.
32
+ */
33
+ export function drawGroundGridSegmentBatch(
34
+ context: CanvasRenderingContext2D,
35
+ batch: PlaybackGroundGridSegmentBatch,
36
+ ): void {
37
+ context.globalAlpha = batch.alpha;
38
+ context.lineWidth = batch.thicknessPx;
39
+ strokePlaybackGroundGridBatch(context, batch);
40
+ }
41
+
42
+ /**
43
+ * Strokes one ground-grid batch using a cached path when the environment supports it.
44
+ *
45
+ * @param context - Canvas 2D drawing context.
46
+ * @param batch - Ordered line-segment batch that shares one render style.
47
+ * @returns Nothing.
48
+ */
49
+ function strokePlaybackGroundGridBatch(
50
+ context: CanvasRenderingContext2D,
51
+ batch: PlaybackGroundGridSegmentBatch,
52
+ ): void {
53
+ if (batch.path) {
54
+ context.stroke(batch.path);
55
+ return;
56
+ }
57
+
58
+ context.beginPath();
59
+ for (const segment of batch.segments) {
60
+ context.moveTo(segment.startXPx, segment.startYPx);
61
+ context.lineTo(segment.endXPx, segment.endYPx);
62
+ }
63
+ context.stroke();
64
+ }
@@ -0,0 +1,207 @@
1
+ import { FLAPPY_GROUND_GRID_FOG_HEIGHT_RATIO } from './playback.background.ground-grid.constants';
2
+ import type {
3
+ PlaybackBackgroundGroundGridSceneContext,
4
+ PlaybackGroundGridHorizontalGeometry,
5
+ PlaybackGroundGridHorizontalGeometryFactory,
6
+ PlaybackGroundGridVerticalGeometry,
7
+ PlaybackGroundGridVerticalGeometryFactory,
8
+ PlaybackGroundGridVerticalSceneMetrics,
9
+ PlaybackGroundGridVerticalSceneMetricsFactory,
10
+ } from './playback.background.ground-grid.types';
11
+
12
+ let cachedViewportSizeKey: string | null = null;
13
+ let cachedFogGradientsByCanvas = new WeakMap<
14
+ HTMLCanvasElement,
15
+ Map<string, CanvasGradient>
16
+ >();
17
+
18
+ const cachedHorizontalGeometryBySceneKey = new Map<
19
+ string,
20
+ PlaybackGroundGridHorizontalGeometry
21
+ >();
22
+ const cachedVerticalSceneMetricsBySceneKey = new Map<
23
+ string,
24
+ PlaybackGroundGridVerticalSceneMetrics
25
+ >();
26
+ const cachedVerticalGeometryByCycleKey = new Map<
27
+ string,
28
+ PlaybackGroundGridVerticalGeometry
29
+ >();
30
+
31
+ /**
32
+ * Ensures ground-grid caches only retain entries for the current viewport size.
33
+ *
34
+ * The ground grid is derived from viewport width and total scene height, so a
35
+ * page resize invalidates every cached geometry variant and fog gradient.
36
+ *
37
+ * @param sceneContext - Current lower-band scene geometry.
38
+ * @returns Stable viewport-size cache key for the current frame.
39
+ */
40
+ export function ensureGroundGridViewportCacheValidity(
41
+ sceneContext: PlaybackBackgroundGroundGridSceneContext,
42
+ ): string {
43
+ const viewportSizeKey = resolveGroundGridViewportCacheKey(sceneContext);
44
+ if (cachedViewportSizeKey === viewportSizeKey) {
45
+ return viewportSizeKey;
46
+ }
47
+
48
+ cachedViewportSizeKey = viewportSizeKey;
49
+ cachedHorizontalGeometryBySceneKey.clear();
50
+ cachedVerticalSceneMetricsBySceneKey.clear();
51
+ cachedVerticalGeometryByCycleKey.clear();
52
+ cachedFogGradientsByCanvas = new WeakMap<
53
+ HTMLCanvasElement,
54
+ Map<string, CanvasGradient>
55
+ >();
56
+ return viewportSizeKey;
57
+ }
58
+
59
+ /**
60
+ * Resolves the viewport-size cache key used by the ground-grid caches.
61
+ *
62
+ * @param sceneContext - Current lower-band scene geometry.
63
+ * @returns Cache key that changes whenever the page size changes.
64
+ */
65
+ export function resolveGroundGridViewportCacheKey(
66
+ sceneContext: PlaybackBackgroundGroundGridSceneContext,
67
+ ): string {
68
+ return `${sceneContext.visibleWorldWidthPx}x${sceneContext.lowerBandBottomYPx}`;
69
+ }
70
+
71
+ /**
72
+ * Resolves the stable local-scene cache key for ground-grid geometry.
73
+ *
74
+ * @param sceneContext - Current lower-band scene geometry.
75
+ * @returns Scene key suitable for static horizontal and vertical cache entries.
76
+ */
77
+ export function resolveGroundGridSceneCacheKey(
78
+ sceneContext: PlaybackBackgroundGroundGridSceneContext,
79
+ ): string {
80
+ return [
81
+ sceneContext.visibleWorldWidthPx,
82
+ sceneContext.alignedHorizonYPx,
83
+ sceneContext.lowerBandTopYPx,
84
+ sceneContext.lowerBandHeightPx,
85
+ sceneContext.lowerBandBottomYPx,
86
+ sceneContext.vanishingPointXPx,
87
+ sceneContext.vanishingPointYPx,
88
+ ].join(':');
89
+ }
90
+
91
+ /**
92
+ * Resolves the cache key for one wrapped vertical-geometry cycle.
93
+ *
94
+ * @param sceneCacheKey - Stable scene key for the active viewport.
95
+ * @param wrappedOffsetPx - Wrapped offset within one lane cycle.
96
+ * @returns Cycle key used for vertical geometry reuse.
97
+ */
98
+ export function resolveGroundGridVerticalCycleCacheKey(
99
+ sceneCacheKey: string,
100
+ wrappedOffsetPx: number,
101
+ ): string {
102
+ return `${sceneCacheKey}|offset:${wrappedOffsetPx}`;
103
+ }
104
+
105
+ /**
106
+ * Resolves cached horizontal geometry for one scene.
107
+ *
108
+ * @param sceneCacheKey - Stable scene key for the active viewport.
109
+ * @param factory - Lazy geometry builder used when the cache misses.
110
+ * @returns Cached horizontal geometry bundle for the scene.
111
+ */
112
+ export function resolveCachedGroundGridHorizontalGeometry(
113
+ sceneCacheKey: string,
114
+ factory: PlaybackGroundGridHorizontalGeometryFactory,
115
+ ): PlaybackGroundGridHorizontalGeometry {
116
+ const cachedGeometry = cachedHorizontalGeometryBySceneKey.get(sceneCacheKey);
117
+ if (cachedGeometry) {
118
+ return cachedGeometry;
119
+ }
120
+
121
+ const resolvedGeometry = factory();
122
+ cachedHorizontalGeometryBySceneKey.set(sceneCacheKey, resolvedGeometry);
123
+ return resolvedGeometry;
124
+ }
125
+
126
+ /**
127
+ * Resolves cached scene metrics for one vertical-grid layout.
128
+ *
129
+ * @param sceneCacheKey - Stable scene key for the active viewport.
130
+ * @param factory - Lazy scene-metrics builder used when the cache misses.
131
+ * @returns Cached vertical scene metrics for the scene.
132
+ */
133
+ export function resolveCachedGroundGridVerticalSceneMetrics(
134
+ sceneCacheKey: string,
135
+ factory: PlaybackGroundGridVerticalSceneMetricsFactory,
136
+ ): PlaybackGroundGridVerticalSceneMetrics {
137
+ const cachedSceneMetrics =
138
+ cachedVerticalSceneMetricsBySceneKey.get(sceneCacheKey);
139
+ if (cachedSceneMetrics) {
140
+ return cachedSceneMetrics;
141
+ }
142
+
143
+ const resolvedSceneMetrics = factory();
144
+ cachedVerticalSceneMetricsBySceneKey.set(sceneCacheKey, resolvedSceneMetrics);
145
+ return resolvedSceneMetrics;
146
+ }
147
+
148
+ /**
149
+ * Resolves cached vertical geometry for one scene and wrapped offset cycle.
150
+ *
151
+ * @param cycleCacheKey - Scene-and-offset cache key for the active frame.
152
+ * @param factory - Lazy geometry builder used when the cache misses.
153
+ * @returns Cached vertical geometry bundle for the cycle.
154
+ */
155
+ export function resolveCachedGroundGridVerticalGeometry(
156
+ cycleCacheKey: string,
157
+ factory: PlaybackGroundGridVerticalGeometryFactory,
158
+ ): PlaybackGroundGridVerticalGeometry {
159
+ const cachedGeometry = cachedVerticalGeometryByCycleKey.get(cycleCacheKey);
160
+ if (cachedGeometry) {
161
+ return cachedGeometry;
162
+ }
163
+
164
+ const resolvedGeometry = factory();
165
+ cachedVerticalGeometryByCycleKey.set(cycleCacheKey, resolvedGeometry);
166
+ return resolvedGeometry;
167
+ }
168
+
169
+ /**
170
+ * Resolves a cached fog gradient for one canvas and local scene.
171
+ *
172
+ * @param context - Canvas 2D drawing context.
173
+ * @param sceneCacheKey - Stable scene key for the active viewport.
174
+ * @param sceneContext - Current lower-band scene geometry.
175
+ * @param fogColor - Theme-owned fog color token.
176
+ * @returns Cached fog gradient aligned to the lower-band scene.
177
+ */
178
+ export function resolveCachedGroundGridFogGradient(
179
+ context: CanvasRenderingContext2D,
180
+ sceneCacheKey: string,
181
+ sceneContext: PlaybackBackgroundGroundGridSceneContext,
182
+ fogColor: string,
183
+ ): CanvasGradient {
184
+ const fogGradientKey = `${sceneCacheKey}|fog:${fogColor}`;
185
+ const canvas = context.canvas;
186
+ const cachedGradientsForCanvas =
187
+ cachedFogGradientsByCanvas.get(canvas) ?? new Map<string, CanvasGradient>();
188
+ const cachedGradient = cachedGradientsForCanvas.get(fogGradientKey);
189
+ if (cachedGradient) {
190
+ return cachedGradient;
191
+ }
192
+
193
+ const fogHeightPx =
194
+ sceneContext.lowerBandHeightPx * FLAPPY_GROUND_GRID_FOG_HEIGHT_RATIO;
195
+ const fogGradient = context.createLinearGradient(
196
+ 0,
197
+ sceneContext.lowerBandTopYPx,
198
+ 0,
199
+ sceneContext.lowerBandTopYPx + fogHeightPx,
200
+ );
201
+ fogGradient.addColorStop(0, fogColor);
202
+ fogGradient.addColorStop(1, 'rgba(0, 0, 0, 0)');
203
+
204
+ cachedGradientsForCanvas.set(fogGradientKey, fogGradient);
205
+ cachedFogGradientsByCanvas.set(canvas, cachedGradientsForCanvas);
206
+ return fogGradient;
207
+ }
@@ -0,0 +1,197 @@
1
+ import { FLAPPY_NEON_PALETTE } from '../../../../constants/constants';
2
+ import { FLAPPY_MAX_DIFFICULTY_PIPE_PITCH_PX } from '../../../../constants/constants.difficulty';
3
+ import type { PlaybackBackgroundGroundGridStyle } from './playback.background.ground-grid.types';
4
+
5
+ /**
6
+ * Number of horizontal depth bands used by the neon ground grid.
7
+ *
8
+ * More bands increase the sense of depth, but they also thicken the lower band
9
+ * visually and add more line work to each frame.
10
+ */
11
+ export const FLAPPY_GROUND_GRID_HORIZONTAL_LINE_COUNT = 16;
12
+
13
+ /**
14
+ * Target visible spacing between adjacent vertical rays at the pipe floor.
15
+ *
16
+ * The lower pipes visually attach to a projected floor band in the grid. The
17
+ * important invariant is phase repeat, not just raw gap width: each new pipe at
18
+ * max difficulty should land on the same relative grid position as the previous
19
+ * one. That requires matching the full pipe-to-pipe pitch, not only the open
20
+ * edge-to-edge gap between pipe bodies.
21
+ */
22
+ export const FLAPPY_GROUND_GRID_TARGET_VERTICAL_LINE_SPACING_PX =
23
+ FLAPPY_MAX_DIFFICULTY_PIPE_PITCH_PX;
24
+
25
+ /**
26
+ * Minimum visible perspective-ray count used on very narrow viewports.
27
+ *
28
+ * Even on a small canvas, the grid still needs at least a few rays to read as
29
+ * perspective instead of a flat block of horizontal stripes.
30
+ */
31
+ export const FLAPPY_GROUND_GRID_MIN_VERTICAL_LINE_COUNT = 2;
32
+
33
+ /**
34
+ * Extra off-screen perspective rays drawn for seamless wrap.
35
+ *
36
+ * Overflow rays prevent the parallax cycle from exposing empty gaps when the
37
+ * wrapped scroll offset lands near a lane boundary.
38
+ */
39
+ export const FLAPPY_GROUND_GRID_VERTICAL_OVERFLOW_COUNT = 1;
40
+
41
+ /**
42
+ * Target screen-space height for one vertical-ray style segment (pixels).
43
+ *
44
+ * Segmenting the rays lets the renderer vary alpha, thickness, and blur by
45
+ * depth rather than drawing each ray with one flat style.
46
+ */
47
+ export const FLAPPY_GROUND_GRID_TARGET_VERTICAL_SEGMENT_HEIGHT_PX = 24;
48
+
49
+ /**
50
+ * Approximate playback frame duration used for deterministic pulse timing.
51
+ *
52
+ * The pulse system is designed to feel stable at ordinary browser animation
53
+ * cadence without requiring access to wall-clock time in every helper.
54
+ */
55
+ export const FLAPPY_GROUND_GRID_APPROX_FRAME_DURATION_MS = 1000 / 60;
56
+
57
+ /**
58
+ * Interval between visible pulse events (milliseconds).
59
+ *
60
+ * A relatively slow cadence keeps the pulses as occasional accent lights rather
61
+ * than a constant distraction under the birds.
62
+ */
63
+ export const FLAPPY_GROUND_GRID_PULSE_INTERVAL_MS = 6000;
64
+
65
+ /**
66
+ * Lifetime of one pulse as it travels across its chosen line (milliseconds).
67
+ *
68
+ * The lifetime is slightly shorter than the full interval so one pulse fades
69
+ * out before the next slot becomes active.
70
+ */
71
+ export const FLAPPY_GROUND_GRID_PULSE_LIFETIME_MS = 5900;
72
+
73
+ /** Peak opacity used by visible pulse squares. */
74
+ export const FLAPPY_GROUND_GRID_PULSE_ALPHA = 0.99;
75
+
76
+ /** Smallest visible pulse square size (pixels). */
77
+ export const FLAPPY_GROUND_GRID_PULSE_MIN_SIZE_PX = 1;
78
+
79
+ /** Largest visible pulse square size (pixels). */
80
+ export const FLAPPY_GROUND_GRID_PULSE_MAX_SIZE_PX = 6;
81
+
82
+ /**
83
+ * Earliest progress ratio allowed for vertical pulse travel.
84
+ *
85
+ * Vertical pulses start a little away from the horizon so they are visible as
86
+ * distinct squares instead of immediately disappearing into compressed depth.
87
+ */
88
+ export const FLAPPY_GROUND_GRID_VERTICAL_PULSE_START_RATIO = 0.14;
89
+
90
+ /**
91
+ * Latest progress ratio allowed for vertical pulse travel.
92
+ *
93
+ * Ending early keeps the pulse out of the extreme foreground, where its square
94
+ * would become too large and visually heavy.
95
+ */
96
+ export const FLAPPY_GROUND_GRID_VERTICAL_PULSE_END_RATIO = 0.62;
97
+
98
+ /** Minimum horizontal line thickness eligible for pulse travel. */
99
+ export const FLAPPY_GROUND_GRID_PULSE_MIN_ELIGIBLE_THICKNESS_PX = 1.5;
100
+
101
+ /**
102
+ * Earliest eligible slice of horizontal lines used for visible pulse picks.
103
+ *
104
+ * This biases horizontal pulses toward the more legible near-midground instead
105
+ * of the compressed lines nearest the horizon.
106
+ */
107
+ export const FLAPPY_GROUND_GRID_PULSE_PREFERRED_HORIZONTAL_START_RATIO = 0.4;
108
+
109
+ /** Horizontal inset that keeps vertical pulse picks away from clipped edges. */
110
+ export const FLAPPY_GROUND_GRID_PULSE_VISIBLE_VIEWPORT_INSET_PX = 24;
111
+
112
+ /**
113
+ * Normalization divisor used for deterministic pulse hash generation.
114
+ *
115
+ * The pulse selection helpers convert unsigned integer hashes into stable
116
+ * floating-point picks in the unit interval.
117
+ */
118
+ export const FLAPPY_GROUND_GRID_UNSIGNED_NORMALIZATION_DIVISOR = 0x1_0000_0000;
119
+
120
+ /**
121
+ * Non-linear exponent used to compress depth lines toward the horizon.
122
+ *
123
+ * This is the main perspective stylization control: higher values bunch more of
124
+ * the depth bands near the horizon and leave broader spacing near the viewer.
125
+ */
126
+ export const FLAPPY_GROUND_GRID_DEPTH_CURVE_EXPONENT = 2.35;
127
+
128
+ /**
129
+ * Near-edge horizontal line offset used for the lower-pipe floor illusion.
130
+ *
131
+ * `1` targets the first usable grid band above the bottom edge rather than the
132
+ * terminal line that coincides with the lower-band boundary itself.
133
+ */
134
+ export const FLAPPY_GROUND_GRID_PIPE_CONNECTION_LINE_OFFSET_FROM_BOTTOM = 1;
135
+
136
+ /**
137
+ * Scroll ratio applied to the moving vertical perspective rays.
138
+ *
139
+ * Keeping the rays slower than gameplay motion makes the grid feel like a deep
140
+ * environmental layer rather than a surface glued to the pipes.
141
+ */
142
+ export const FLAPPY_GROUND_GRID_SCROLL_RATIO = 0.16;
143
+
144
+ /**
145
+ * Decimal precision used when quantizing the wrapped vertical-ray offset.
146
+ *
147
+ * Quantization stabilizes cache reuse by preventing tiny floating-point drift
148
+ * from generating effectively identical geometry variants.
149
+ */
150
+ export const FLAPPY_GROUND_GRID_SCROLL_OFFSET_QUANTIZATION_DECIMALS = 3;
151
+
152
+ /** Minimum alpha used by the farthest horizontal depth lines. */
153
+ export const FLAPPY_GROUND_GRID_MIN_ALPHA = 0.12;
154
+
155
+ /** Maximum alpha used by the nearest depth and perspective lines. */
156
+ export const FLAPPY_GROUND_GRID_MAX_ALPHA = 0.58;
157
+
158
+ /** Blur radius used by the farthest depth lines near the horizon. */
159
+ export const FLAPPY_GROUND_GRID_MAX_BLUR_PX = 6;
160
+
161
+ /** Blur radius used by the nearest depth lines at the bottom edge. */
162
+ export const FLAPPY_GROUND_GRID_MIN_BLUR_PX = 0;
163
+
164
+ /** Minimum stroke width used by far depth lines. */
165
+ export const FLAPPY_GROUND_GRID_MIN_THICKNESS_PX = 1;
166
+
167
+ /** Maximum stroke width used by near depth lines. */
168
+ export const FLAPPY_GROUND_GRID_MAX_THICKNESS_PX = 3;
169
+
170
+ /**
171
+ * Height ratio reserved for the subtle lower-band neon fog wash.
172
+ *
173
+ * The fog sits in the lower portion of the band so it enriches the foreground
174
+ * without muting the crisp horizon seam.
175
+ */
176
+ export const FLAPPY_GROUND_GRID_FOG_HEIGHT_RATIO = 0.45;
177
+
178
+ /**
179
+ * Peak opacity used by the lower-band neon fog wash.
180
+ *
181
+ * The fog should tint the band, not obscure the line geometry, so the opacity
182
+ * is intentionally modest.
183
+ */
184
+ export const FLAPPY_GROUND_GRID_FOG_ALPHA = 0.24;
185
+
186
+ /**
187
+ * Frozen neon style bundle reused by the playback ground-grid renderer.
188
+ *
189
+ * The values stay theme-owned but are materialized once so the renderer does
190
+ * not allocate a new style object during every frame.
191
+ */
192
+ export const FLAPPY_BACKGROUND_GROUND_GRID_STYLE: PlaybackBackgroundGroundGridStyle =
193
+ Object.freeze({
194
+ lineColor: FLAPPY_NEON_PALETTE.groundGridLine,
195
+ fogColor: FLAPPY_NEON_PALETTE.groundGridFog,
196
+ pulseFillColor: FLAPPY_NEON_PALETTE.groundGridPulseFill,
197
+ });
@@ -0,0 +1,114 @@
1
+ import {
2
+ FLAPPY_GROUND_GRID_PULSE_MIN_ELIGIBLE_THICKNESS_PX,
3
+ FLAPPY_GROUND_GRID_PULSE_PREFERRED_HORIZONTAL_START_RATIO,
4
+ } from './playback.background.ground-grid.constants';
5
+ import type {
6
+ PlaybackGroundGridLineSegment,
7
+ PlaybackGroundGridPulsePath,
8
+ PlaybackGroundGridSegmentBatch,
9
+ } from './playback.background.ground-grid.types';
10
+
11
+ /**
12
+ * Groups line segments into ordered style batches for lower-overhead drawing.
13
+ *
14
+ * @param segments - Ordered line segments that should preserve draw grouping.
15
+ * @returns Ordered style batches that can be stroked with fewer state changes.
16
+ */
17
+ export function groupPlaybackGroundGridSegmentsByStyle(
18
+ segments: readonly PlaybackGroundGridLineSegment[],
19
+ ): readonly PlaybackGroundGridSegmentBatch[] {
20
+ const groupedSegmentsByStyle = new Map<
21
+ string,
22
+ PlaybackGroundGridLineSegment[]
23
+ >();
24
+
25
+ for (const segment of segments) {
26
+ const styleKey = `${segment.alpha}:${segment.blurPx}:${segment.thicknessPx}`;
27
+ const existingGroup = groupedSegmentsByStyle.get(styleKey);
28
+ if (existingGroup) {
29
+ existingGroup.push(segment);
30
+ continue;
31
+ }
32
+
33
+ groupedSegmentsByStyle.set(styleKey, [segment]);
34
+ }
35
+
36
+ const segmentBatches: PlaybackGroundGridSegmentBatch[] = [];
37
+ for (const groupedSegments of groupedSegmentsByStyle.values()) {
38
+ const firstSegment = groupedSegments[0];
39
+ segmentBatches.push({
40
+ alpha: firstSegment.alpha,
41
+ blurPx: firstSegment.blurPx,
42
+ path: resolvePlaybackGroundGridBatchPath(groupedSegments),
43
+ thicknessPx: firstSegment.thicknessPx,
44
+ segments: groupedSegments,
45
+ });
46
+ }
47
+
48
+ return segmentBatches;
49
+ }
50
+
51
+ /**
52
+ * Prefers the nearer, thicker horizontal tracks when picking a pulse lane.
53
+ *
54
+ * @param horizontalLines - Visible horizontal grid bands.
55
+ * @returns Pulse-eligible horizontal paths biased toward the foreground.
56
+ */
57
+ export function resolvePlaybackGroundGridPreferredHorizontalPulsePaths(
58
+ horizontalLines: readonly PlaybackGroundGridLineSegment[],
59
+ ): readonly PlaybackGroundGridPulsePath[] {
60
+ const eligibleHorizontalPulsePaths: PlaybackGroundGridPulsePath[] = [];
61
+
62
+ for (const horizontalLine of horizontalLines) {
63
+ if (
64
+ horizontalLine.thicknessPx <
65
+ FLAPPY_GROUND_GRID_PULSE_MIN_ELIGIBLE_THICKNESS_PX
66
+ ) {
67
+ continue;
68
+ }
69
+
70
+ eligibleHorizontalPulsePaths.push({
71
+ orientation: 'horizontal',
72
+ startXPx: horizontalLine.startXPx,
73
+ startYPx: horizontalLine.startYPx,
74
+ endXPx: horizontalLine.endXPx,
75
+ endYPx: horizontalLine.endYPx,
76
+ thicknessPx: horizontalLine.thicknessPx,
77
+ });
78
+ }
79
+
80
+ if (eligibleHorizontalPulsePaths.length === 0) {
81
+ return eligibleHorizontalPulsePaths;
82
+ }
83
+
84
+ const preferredStartIndex = Math.min(
85
+ eligibleHorizontalPulsePaths.length - 1,
86
+ Math.floor(
87
+ eligibleHorizontalPulsePaths.length *
88
+ FLAPPY_GROUND_GRID_PULSE_PREFERRED_HORIZONTAL_START_RATIO,
89
+ ),
90
+ );
91
+ return eligibleHorizontalPulsePaths.slice(preferredStartIndex);
92
+ }
93
+
94
+ /**
95
+ * Resolves one cached draw-ready path for a grouped segment batch.
96
+ *
97
+ * @param segments - Ordered line segments that belong to one style batch.
98
+ * @returns Cached Path2D when available, otherwise null.
99
+ */
100
+ function resolvePlaybackGroundGridBatchPath(
101
+ segments: readonly PlaybackGroundGridLineSegment[],
102
+ ): Path2D | null {
103
+ if (typeof Path2D !== 'function') {
104
+ return null;
105
+ }
106
+
107
+ const batchPath = new Path2D();
108
+ for (const segment of segments) {
109
+ batchPath.moveTo(segment.startXPx, segment.startYPx);
110
+ batchPath.lineTo(segment.endXPx, segment.endYPx);
111
+ }
112
+
113
+ return batchPath;
114
+ }
@@ -0,0 +1,96 @@
1
+ import {
2
+ FLAPPY_MAX_DIFFICULTY_PIPE_PITCH_PX,
3
+ FLAPPY_PIPE_SPEED_MAX_PX_PER_FRAME,
4
+ FLAPPY_PIPE_SPAWN_INTERVAL_MIN_FRAMES,
5
+ } from '../../../../constants/constants.difficulty';
6
+ import {
7
+ buildPlaybackGroundGridVerticalSceneMetrics,
8
+ resolvePlaybackGroundGridVerticalCycleContext,
9
+ } from './playback.background.ground-grid.geometry.layout.utils';
10
+ import { resolvePlaybackGroundGridPipeConnectionProfile } from './playback.background.ground-grid.math.utils';
11
+ import type { PlaybackBackgroundGroundGridSceneContext } from './playback.background.ground-grid.types';
12
+
13
+ describe('buildPlaybackGroundGridVerticalSceneMetrics', () => {
14
+ it('matches pipe-floor lane spacing to the actual max-difficulty pipe pitch', () => {
15
+ const sceneContext = createSceneContext();
16
+ const verticalSceneMetrics =
17
+ buildPlaybackGroundGridVerticalSceneMetrics(sceneContext);
18
+ const pipeConnectionProfile =
19
+ resolvePlaybackGroundGridPipeConnectionProfile(
20
+ sceneContext.lowerBandBottomYPx,
21
+ );
22
+ const retainedWidthRatioAtPipeConnection =
23
+ (sceneContext.vanishingPointYPx - pipeConnectionProfile.pipeFloorYPx) /
24
+ (sceneContext.vanishingPointYPx - sceneContext.lowerBandBottomYPx);
25
+ const projectedLaneSpacingPx =
26
+ verticalSceneMetrics.safeLaneSpacingPx *
27
+ retainedWidthRatioAtPipeConnection;
28
+
29
+ expect(projectedLaneSpacingPx).toBeCloseTo(
30
+ FLAPPY_MAX_DIFFICULTY_PIPE_PITCH_PX,
31
+ 6,
32
+ );
33
+ });
34
+
35
+ it('repeats the same grid phase after one max-difficulty spawn interval', () => {
36
+ const sceneContext = createSceneContext();
37
+ const verticalSceneMetrics =
38
+ buildPlaybackGroundGridVerticalSceneMetrics(sceneContext);
39
+ const pipeConnectionProfile =
40
+ resolvePlaybackGroundGridPipeConnectionProfile(
41
+ sceneContext.lowerBandBottomYPx,
42
+ );
43
+ const retainedWidthRatioAtPipeConnection =
44
+ (sceneContext.vanishingPointYPx - pipeConnectionProfile.pipeFloorYPx) /
45
+ (sceneContext.vanishingPointYPx - sceneContext.lowerBandBottomYPx);
46
+ const projectedLaneSpacingPx =
47
+ verticalSceneMetrics.safeLaneSpacingPx *
48
+ retainedWidthRatioAtPipeConnection;
49
+ const projectedTravelPerSpawnPx =
50
+ FLAPPY_PIPE_SPEED_MAX_PX_PER_FRAME *
51
+ FLAPPY_PIPE_SPAWN_INTERVAL_MIN_FRAMES;
52
+
53
+ expect(projectedTravelPerSpawnPx % projectedLaneSpacingPx).toBeCloseTo(
54
+ 0,
55
+ 6,
56
+ );
57
+ });
58
+
59
+ it('retains enough rays to cover the full visible horizon span', () => {
60
+ const sceneContext = createSceneContext();
61
+ const verticalSceneMetrics =
62
+ buildPlaybackGroundGridVerticalSceneMetrics(sceneContext);
63
+ const coveredAnchorSpanPx =
64
+ (verticalSceneMetrics.totalVisibleLaneCount - 1) *
65
+ verticalSceneMetrics.safeLaneSpacingPx;
66
+
67
+ expect(coveredAnchorSpanPx).toBeGreaterThanOrEqual(
68
+ verticalSceneMetrics.visibleAnchorBounds.anchorSpanPx,
69
+ );
70
+ });
71
+ });
72
+
73
+ describe('resolvePlaybackGroundGridVerticalCycleContext', () => {
74
+ it('preserves the lane spacing that the viewport metrics resolved', () => {
75
+ const verticalCycleContext = resolvePlaybackGroundGridVerticalCycleContext(
76
+ 120,
77
+ 512,
78
+ 960,
79
+ );
80
+
81
+ expect(verticalCycleContext.safeLaneSpacingPx).toBe(120);
82
+ });
83
+ });
84
+
85
+ function createSceneContext(): PlaybackBackgroundGroundGridSceneContext {
86
+ return {
87
+ viewportOffsetXPx: 0,
88
+ visibleWorldWidthPx: 288,
89
+ alignedHorizonYPx: 339,
90
+ lowerBandTopYPx: 341,
91
+ lowerBandHeightPx: 171,
92
+ lowerBandBottomYPx: 512,
93
+ vanishingPointXPx: 144,
94
+ vanishingPointYPx: 256,
95
+ };
96
+ }