@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
@@ -0,0 +1,291 @@
1
+ import type { Neat } from '../../../../src/neataptic';
2
+ import type Network from '../../../../src/architecture/network';
3
+ import { createXorshift32 } from '../rng';
4
+ import {
5
+ commitObservationMemoryStep,
6
+ resolveFlapDecision,
7
+ resolveObservationVector,
8
+ } from '../browser-entry/browser-entry.observation.utils';
9
+ import {
10
+ createBirdColor,
11
+ sampleGapCenterY,
12
+ } from '../browser-entry/browser-entry.spawn.utils';
13
+ import type {
14
+ WorkerHeuristicObservationFeatures,
15
+ WorkerPopulationPipe,
16
+ } from './flappy-evolution-worker.types';
17
+ import { FLAPPY_BIRD_VIEWPORT_X_RATIO } from '../constants/constants';
18
+ import {
19
+ FLAPPY_BIRD_RADIUS_PX,
20
+ FLAPPY_BIRD_X_PX,
21
+ FLAPPY_PIPE_COLLISION_ENTRANCE_EXPAND_PX,
22
+ FLAPPY_PIPE_COLLISION_SIDE_EXPAND_PX,
23
+ FLAPPY_CONTROL_SUBSTEPS_PER_FRAME,
24
+ FLAPPY_FLAP_VELOCITY_PX_PER_FRAME,
25
+ FLAPPY_GRAVITY_PX_PER_FRAME2,
26
+ FLAPPY_MAX_FALL_SPEED_PX_PER_FRAME,
27
+ FLAPPY_PIPE_WIDTH_PX,
28
+ FLAPPY_WORLD_HEIGHT_PX,
29
+ } from '../constants/constants';
30
+ import {
31
+ FLAPPY_WORKER_GEN0_PRETRAIN_BATCH_SIZE,
32
+ FLAPPY_WORKER_GEN0_PRETRAIN_BIAS_NOISE_STDDEV,
33
+ FLAPPY_WORKER_GEN0_PRETRAIN_ITERATIONS,
34
+ FLAPPY_WORKER_GEN0_PRETRAIN_RATE,
35
+ FLAPPY_WORKER_GEN0_PRETRAIN_SAMPLE_COUNT,
36
+ FLAPPY_WORKER_GEN0_PRETRAIN_VISIBLE_WORLD_WIDTH_PX,
37
+ FLAPPY_WORKER_GEN0_PRETRAIN_WEIGHT_NOISE_STDDEV,
38
+ } from './flappy-evolution-worker.constants';
39
+ import {
40
+ createSharedObservationMemoryState,
41
+ resolveAdaptiveDifficultyProfile,
42
+ } from '../flappy.simulation.shared.utils';
43
+
44
+ /**
45
+ * State carried between generation requests for one worker runtime.
46
+ */
47
+ export interface WorkerWarmStartState {
48
+ workerInitSeed: number;
49
+ generationZeroWarmStartApplied: boolean;
50
+ }
51
+
52
+ /**
53
+ * Applies a one-time generation-0 warm-start to improve initial demo quality.
54
+ *
55
+ * Educational note:
56
+ * The worker entry should stay protocol-first. This service owns the short
57
+ * supervised bootstrap pass that nudges generation 0 away from pure noise while
58
+ * preserving the later NEAT-driven search loop.
59
+ *
60
+ * @param neatController - Initialized NEAT runtime.
61
+ * @param warmStartState - Mutable warm-start lifecycle state.
62
+ * @returns Promise resolved when warm-start evaluation finishes.
63
+ * @example
64
+ * ```ts
65
+ * await warmStartWorkerGenerationZeroIfNeeded(neatRuntime, {
66
+ * workerInitSeed: 123,
67
+ * generationZeroWarmStartApplied: false,
68
+ * });
69
+ * ```
70
+ */
71
+ export async function warmStartWorkerGenerationZeroIfNeeded(
72
+ neatController: Neat,
73
+ warmStartState: WorkerWarmStartState,
74
+ ): Promise<void> {
75
+ // Step 1: Exit fast when warm-start is already processed.
76
+ if (warmStartState.generationZeroWarmStartApplied) return;
77
+
78
+ // Step 2: Warm-start only generation 0 to avoid skewing later evolution.
79
+ if (neatController.generation !== 0) {
80
+ warmStartState.generationZeroWarmStartApplied = true;
81
+ return;
82
+ }
83
+
84
+ // Step 3: Validate population availability.
85
+ const population = neatController.population;
86
+ if (!Array.isArray(population) || population.length === 0) {
87
+ warmStartState.generationZeroWarmStartApplied = true;
88
+ return;
89
+ }
90
+
91
+ // Step 4: Build a small synthetic dataset labeled by a simple heuristic.
92
+ const warmStartRng = createXorshift32(
93
+ warmStartState.workerInitSeed ^ 0x9e37_79b9,
94
+ );
95
+ const trainingSet = buildHeuristicPretrainSet(
96
+ warmStartRng,
97
+ FLAPPY_WORKER_GEN0_PRETRAIN_SAMPLE_COUNT,
98
+ );
99
+
100
+ // Step 5: Train a single template network, then seed the whole population from it.
101
+ const templateNetwork = population[0]?.clone();
102
+ if (!templateNetwork) {
103
+ warmStartState.generationZeroWarmStartApplied = true;
104
+ return;
105
+ }
106
+
107
+ try {
108
+ templateNetwork.train(trainingSet, {
109
+ iterations: FLAPPY_WORKER_GEN0_PRETRAIN_ITERATIONS,
110
+ rate: FLAPPY_WORKER_GEN0_PRETRAIN_RATE,
111
+ batchSize: FLAPPY_WORKER_GEN0_PRETRAIN_BATCH_SIZE,
112
+ optimizer: 'adam',
113
+ mixedPrecision: false,
114
+ });
115
+ } catch {
116
+ // If training fails for any reason, fall back to pure noise seeding.
117
+ }
118
+
119
+ // Step 6: Copy trained weights/biases into each genome with small noise for diversity.
120
+ for (const genome of population) {
121
+ applyTemplateWeightsWithNoise(genome, templateNetwork, warmStartRng, {
122
+ weightStdDev: FLAPPY_WORKER_GEN0_PRETRAIN_WEIGHT_NOISE_STDDEV,
123
+ biasStdDev: FLAPPY_WORKER_GEN0_PRETRAIN_BIAS_NOISE_STDDEV,
124
+ });
125
+ (genome as unknown as { score?: number }).score = undefined;
126
+ }
127
+
128
+ warmStartState.generationZeroWarmStartApplied = true;
129
+ }
130
+
131
+ /**
132
+ * Builds synthetic supervised samples for generation-0 behavior cloning.
133
+ *
134
+ * @param rng - Deterministic random source.
135
+ * @param sampleCount - Requested number of synthetic samples.
136
+ * @returns Supervised dataset of input/output pairs.
137
+ */
138
+ function buildHeuristicPretrainSet(
139
+ rng: ReturnType<typeof createXorshift32>,
140
+ sampleCount: number,
141
+ ): Array<{ input: number[]; output: number[] }> {
142
+ // Step 1: Resolve bounded sample count and a baseline difficulty profile.
143
+ const clampedSampleCount = Math.max(8, Math.trunc(sampleCount));
144
+ const difficultyProfile = resolveAdaptiveDifficultyProfile(0, 1);
145
+ const trainingSet: Array<{ input: number[]; output: number[] }> = [];
146
+
147
+ // Step 2: Sample state tuples, encode observations, and attach heuristic labels.
148
+ for (let sampleIndex = 0; sampleIndex < clampedSampleCount; sampleIndex++) {
149
+ const pipeGapPx = difficultyProfile.pipeGapPx;
150
+ const gapHalfPx = pipeGapPx * 0.5;
151
+
152
+ const birdYPx = rng.nextFloat01() * FLAPPY_WORLD_HEIGHT_PX;
153
+ const velocityYPxPerFrame =
154
+ (rng.nextFloat01() * 2 - 1) * FLAPPY_MAX_FALL_SPEED_PX_PER_FRAME;
155
+
156
+ const pipeXMinPx = FLAPPY_BIRD_X_PX + 40;
157
+ const pipeXMaxPx =
158
+ FLAPPY_BIRD_X_PX +
159
+ FLAPPY_WORKER_GEN0_PRETRAIN_VISIBLE_WORLD_WIDTH_PX * 0.92;
160
+ const pipeXSamplePx =
161
+ pipeXMinPx + rng.nextFloat01() * Math.max(1, pipeXMaxPx - pipeXMinPx);
162
+
163
+ const minGapCenterYPx = gapHalfPx;
164
+ const maxGapCenterYPx = Math.max(
165
+ minGapCenterYPx,
166
+ FLAPPY_WORLD_HEIGHT_PX - gapHalfPx,
167
+ );
168
+ const gapCenterYPx =
169
+ minGapCenterYPx + rng.nextFloat01() * (maxGapCenterYPx - minGapCenterYPx);
170
+
171
+ const pipes: WorkerPopulationPipe[] = [
172
+ {
173
+ id: 1,
174
+ xPx: pipeXSamplePx,
175
+ gapCenterYPx,
176
+ gapSizePx: pipeGapPx,
177
+ },
178
+ ];
179
+
180
+ const observationMemoryState = createSharedObservationMemoryState();
181
+ const observation = resolveObservationVector(
182
+ birdYPx,
183
+ velocityYPxPerFrame,
184
+ pipes,
185
+ FLAPPY_WORKER_GEN0_PRETRAIN_VISIBLE_WORLD_WIDTH_PX,
186
+ FLAPPY_WORLD_HEIGHT_PX,
187
+ difficultyProfile,
188
+ difficultyProfile.pipeSpawnIntervalFrames,
189
+ observationMemoryState,
190
+ );
191
+
192
+ const shouldFlap = resolveHeuristicTeacherFlapDecision(
193
+ observation.observationFeatures,
194
+ );
195
+ trainingSet.push({
196
+ input: observation.observationVector,
197
+ output: shouldFlap ? [0, 1] : [1, 0],
198
+ });
199
+ }
200
+
201
+ // Step 3: Return immutable training pairs consumed by Network.train.
202
+ return trainingSet;
203
+ }
204
+
205
+ /**
206
+ * Heuristic teacher policy used to label synthetic pretraining samples.
207
+ *
208
+ * @param features - Structured observation features for one synthetic state.
209
+ * @returns True when the teacher says to flap.
210
+ */
211
+ function resolveHeuristicTeacherFlapDecision(
212
+ features: WorkerHeuristicObservationFeatures,
213
+ ): boolean {
214
+ // Step 1: Resolve the few interpretable teacher conditions.
215
+ const isBelowNextGapCenter = features.normalizedDeltaToNextGap > 0.035;
216
+ const isNotAlreadyRisingFast = features.normalizedVelocity > -0.25;
217
+ const isNearGapEntry = features.normalizedFramesToGapEntry < 0.8;
218
+ const isUrgent = features.normalizedEntryUrgency > 0.18;
219
+
220
+ // Step 2: Fold the teacher decision from those conditions.
221
+ return (
222
+ isBelowNextGapCenter &&
223
+ isNotAlreadyRisingFast &&
224
+ (isNearGapEntry || isUrgent)
225
+ );
226
+ }
227
+
228
+ /**
229
+ * Copies template parameters into a genome and injects small Gaussian noise.
230
+ *
231
+ * @param genome - Target genome to mutate in-place.
232
+ * @param template - Trained template source network.
233
+ * @param rng - Deterministic random source for noise sampling.
234
+ * @param noise - Standard deviations for weight and bias perturbations.
235
+ * @returns Nothing.
236
+ */
237
+ function applyTemplateWeightsWithNoise(
238
+ genome: Network,
239
+ template: Network,
240
+ rng: ReturnType<typeof createXorshift32>,
241
+ noise: { weightStdDev: number; biasStdDev: number },
242
+ ): void {
243
+ // Step 1: Clamp noise scales to valid non-negative values.
244
+ const weightStdDev = Math.max(0, noise.weightStdDev);
245
+ const biasStdDev = Math.max(0, noise.biasStdDev);
246
+
247
+ // Step 2: Copy node biases with additive Gaussian noise.
248
+ const genomeNodes = genome.nodes;
249
+ const templateNodes = template.nodes;
250
+ const nodeCopyCount = Math.min(genomeNodes.length, templateNodes.length);
251
+ for (let nodeIndex = 0; nodeIndex < nodeCopyCount; nodeIndex++) {
252
+ const templateBias = templateNodes[nodeIndex]?.bias ?? 0;
253
+ genomeNodes[nodeIndex].bias =
254
+ templateBias + sampleGaussian(rng) * biasStdDev;
255
+ }
256
+
257
+ // Step 3: Copy connection weights with additive Gaussian noise.
258
+ const genomeConnections = genome.connections;
259
+ const templateConnections = template.connections;
260
+ const connectionCopyCount = Math.min(
261
+ genomeConnections.length,
262
+ templateConnections.length,
263
+ );
264
+ for (
265
+ let connectionIndex = 0;
266
+ connectionIndex < connectionCopyCount;
267
+ connectionIndex++
268
+ ) {
269
+ const templateWeight = templateConnections[connectionIndex]?.weight ?? 0;
270
+ genomeConnections[connectionIndex].weight =
271
+ templateWeight + sampleGaussian(rng) * weightStdDev;
272
+ }
273
+ }
274
+
275
+ /**
276
+ * Samples one standard-normal value using the Box-Muller transform.
277
+ *
278
+ * @param rng - Deterministic random source.
279
+ * @returns One approximately standard-normal random value.
280
+ */
281
+ function sampleGaussian(rng: ReturnType<typeof createXorshift32>): number {
282
+ // Step 1: Avoid log(0) by flooring uniforms away from zero.
283
+ const epsilon = 1e-12;
284
+ const uniformA = Math.max(epsilon, rng.nextFloat01());
285
+ const uniformB = Math.max(epsilon, rng.nextFloat01());
286
+
287
+ // Step 2: Convert two uniforms into one normal sample.
288
+ const magnitude = Math.sqrt(-2 * Math.log(uniformA));
289
+ const angle = 2 * Math.PI * uniformB;
290
+ return magnitude * Math.cos(angle);
291
+ }
@@ -16,6 +16,11 @@ export {
16
16
  clampValue,
17
17
  interpolateValue,
18
18
  } from './simulation-shared/simulation-shared.math.utils';
19
+ export {
20
+ computeMean,
21
+ computePercentile,
22
+ computePopulationStandardDeviation,
23
+ } from './simulation-shared/simulation-shared.statistics.utils';
19
24
  export {
20
25
  resolveNextSpawnGapCenterY,
21
26
  resolveNextSpawnGapSize,