@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.
- package/.github/agents/boundary-mapper.agent.md +29 -0
- package/.github/agents/docs-scout.agent.md +29 -0
- package/.github/agents/plan-scout.agent.md +29 -0
- package/.github/agents/solid-split.agent.md +138 -0
- package/.github/copilot-instructions.md +103 -0
- package/package.json +6 -3
- package/plans/ES2023 migration +13 -8
- package/plans/Evolution_Training_Interoperability_Contracts.md +1 -1
- package/plans/Interactive_Examples_and_Learning_Path.md +10 -2
- package/plans/Memory_Optimization.md +3 -3
- package/plans/README.md +63 -0
- package/plans/Roadmap.md +15 -3
- package/plans/asciiMaze_SOLID_split.done.md +130 -0
- package/plans/flappy_bird_SOLID_split.done.md +67 -0
- package/scripts/assets/theme.css +221 -34
- package/scripts/copy-examples.mjs +9 -5
- package/scripts/export-onnx.mjs +3 -3
- package/scripts/generate-bench-tables.mjs +10 -10
- package/scripts/generate-bench-tables.ts +10 -10
- package/scripts/generate-docs.ts +1415 -449
- package/scripts/render-docs-html.ts +15 -8
- package/src/README.md +101 -223
- package/src/architecture/README.md +57 -185
- package/src/architecture/layer/README.md +38 -38
- package/src/architecture/network/README.md +33 -31
- package/src/architecture/network/activate/README.md +77 -77
- package/src/architecture/network/connect/README.md +15 -13
- package/src/architecture/network/deterministic/README.md +7 -7
- package/src/architecture/network/evolve/README.md +44 -44
- package/src/architecture/network/gating/README.md +20 -20
- package/src/architecture/network/genetic/README.md +51 -51
- package/src/architecture/network/mutate/README.md +97 -97
- package/src/architecture/network/onnx/README.md +264 -264
- package/src/architecture/network/prune/README.md +39 -39
- package/src/architecture/network/remove/README.md +26 -26
- package/src/architecture/network/serialize/README.md +56 -56
- package/src/architecture/network/slab/README.md +61 -61
- package/src/architecture/network/standalone/README.md +24 -24
- package/src/architecture/network/stats/README.md +9 -9
- package/src/architecture/network/topology/README.md +46 -46
- package/src/architecture/network/training/README.md +21 -21
- package/src/methods/README.md +9 -87
- package/src/multithreading/README.md +8 -77
- package/src/multithreading/workers/README.md +2 -2
- package/src/multithreading/workers/browser/README.md +0 -6
- package/src/multithreading/workers/node/README.md +0 -3
- package/src/neat/README.md +562 -568
- package/src/utils/README.md +18 -18
- package/test/examples/asciiMaze/README.md +59 -59
- package/test/examples/asciiMaze/asciiMaze.e2e.test.ts +14 -9
- package/test/examples/asciiMaze/browser-entry/README.md +196 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.abort.services.ts +95 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.constants.ts +23 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.curriculum.services.ts +115 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.globals.services.ts +106 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.host.services.ts +157 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.services.ts +14 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.ts +129 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.types.ts +120 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.utils.ts +98 -0
- package/test/examples/asciiMaze/browser-entry.ts +10 -576
- package/test/examples/asciiMaze/dashboardManager/README.md +276 -0
- package/test/examples/asciiMaze/dashboardManager/archive/README.md +16 -0
- package/test/examples/asciiMaze/dashboardManager/archive/dashboardManager.archive.services.ts +267 -0
- package/test/examples/asciiMaze/dashboardManager/dashboardManager.constants.ts +35 -0
- package/test/examples/asciiMaze/dashboardManager/dashboardManager.services.ts +103 -0
- package/test/examples/asciiMaze/dashboardManager/dashboardManager.ts +181 -0
- package/test/examples/asciiMaze/dashboardManager/dashboardManager.types.ts +267 -0
- package/test/examples/asciiMaze/dashboardManager/dashboardManager.utils.ts +254 -0
- package/test/examples/asciiMaze/dashboardManager/live/README.md +14 -0
- package/test/examples/asciiMaze/dashboardManager/live/dashboardManager.live.services.ts +264 -0
- package/test/examples/asciiMaze/dashboardManager/telemetry/README.md +47 -0
- package/test/examples/asciiMaze/dashboardManager/telemetry/dashboardManager.telemetry.services.ts +513 -0
- package/test/examples/asciiMaze/dashboardManager.ts +13 -2335
- package/test/examples/asciiMaze/evolutionEngine/README.md +1058 -0
- package/test/examples/asciiMaze/evolutionEngine/curriculumPhase.ts +90 -0
- package/test/examples/asciiMaze/evolutionEngine/engineState.constants.ts +36 -0
- package/test/examples/asciiMaze/evolutionEngine/engineState.ts +58 -513
- package/test/examples/asciiMaze/evolutionEngine/engineState.types.ts +212 -0
- package/test/examples/asciiMaze/evolutionEngine/engineState.utils.ts +301 -0
- package/test/examples/asciiMaze/evolutionEngine/evolutionEngine.types.ts +445 -0
- package/test/examples/asciiMaze/evolutionEngine/evolutionLoop.ts +81 -50
- package/test/examples/asciiMaze/evolutionEngine/optionsAndSetup.ts +2 -4
- package/test/examples/asciiMaze/evolutionEngine/populationDynamics.ts +17 -33
- package/test/examples/asciiMaze/evolutionEngine/populationPruning.ts +1 -1
- package/test/examples/asciiMaze/evolutionEngine/rngAndTiming.ts +1 -2
- package/test/examples/asciiMaze/evolutionEngine/sampling.ts +1 -1
- package/test/examples/asciiMaze/evolutionEngine/scratchPools.ts +2 -5
- package/test/examples/asciiMaze/evolutionEngine/setupHelpers.ts +30 -37
- package/test/examples/asciiMaze/evolutionEngine/telemetryMetrics.ts +16 -58
- package/test/examples/asciiMaze/evolutionEngine/trainingWarmStart.ts +2 -2
- package/test/examples/asciiMaze/evolutionEngine.ts +55 -55
- package/test/examples/asciiMaze/fitness.ts +2 -2
- package/test/examples/asciiMaze/fitness.types.ts +65 -0
- package/test/examples/asciiMaze/interfaces.ts +64 -1352
- package/test/examples/asciiMaze/mazeMovement/README.md +356 -0
- package/test/examples/asciiMaze/mazeMovement/finalization/README.md +49 -0
- package/test/examples/asciiMaze/mazeMovement/finalization/mazeMovement.finalization.ts +138 -0
- package/test/examples/asciiMaze/mazeMovement/mazeMovement.constants.ts +101 -0
- package/test/examples/asciiMaze/mazeMovement/mazeMovement.services.ts +230 -0
- package/test/examples/asciiMaze/mazeMovement/mazeMovement.ts +299 -0
- package/test/examples/asciiMaze/mazeMovement/mazeMovement.types.ts +185 -0
- package/test/examples/asciiMaze/mazeMovement/mazeMovement.utils.ts +153 -0
- package/test/examples/asciiMaze/mazeMovement/policy/README.md +91 -0
- package/test/examples/asciiMaze/mazeMovement/policy/mazeMovement.policy.ts +467 -0
- package/test/examples/asciiMaze/mazeMovement/runtime/README.md +95 -0
- package/test/examples/asciiMaze/mazeMovement/runtime/mazeMovement.runtime.ts +354 -0
- package/test/examples/asciiMaze/mazeMovement/shaping/README.md +124 -0
- package/test/examples/asciiMaze/mazeMovement/shaping/mazeMovement.shaping.ts +459 -0
- package/test/examples/asciiMaze/mazeMovement.ts +12 -2978
- package/test/examples/flappy_bird/Trace-20260309T191949.json +24124 -0
- package/test/examples/flappy_bird/browser-entry/README.md +1129 -0
- package/test/examples/flappy_bird/browser-entry/browser-entry.host.utils.ts +4 -324
- package/test/examples/flappy_bird/browser-entry/browser-entry.network-view.utils.ts +6 -399
- package/test/examples/flappy_bird/browser-entry/browser-entry.playback.utils.ts +1 -717
- package/test/examples/flappy_bird/browser-entry/browser-entry.spawn.utils.ts +11 -31
- package/test/examples/flappy_bird/browser-entry/browser-entry.visualization.utils.ts +15 -893
- package/test/examples/flappy_bird/browser-entry/host/README.md +307 -0
- package/test/examples/flappy_bird/browser-entry/host/host.resize.service.ts +1 -295
- package/test/examples/flappy_bird/browser-entry/host/host.ts +562 -6
- package/test/examples/flappy_bird/browser-entry/host/resize/README.md +274 -0
- package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.constants.ts +31 -0
- package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.services.ts +360 -0
- package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.ts +117 -0
- package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.types.ts +63 -0
- package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.utils.ts +250 -0
- package/test/examples/flappy_bird/browser-entry/network-view/README.md +399 -0
- package/test/examples/flappy_bird/browser-entry/network-view/network-view.topology.utils.ts +255 -0
- package/test/examples/flappy_bird/browser-entry/network-view/network-view.ts +802 -7
- package/test/examples/flappy_bird/browser-entry/playback/README.md +684 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/README.md +277 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/README.md +770 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.cache.services.ts +178 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.constants.ts +107 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.geometry.utils.ts +518 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.math.utils.ts +117 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.pulse.utils.ts +233 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.services.ts +211 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.ts +48 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.types.ts +212 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.utils.ts +81 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.cache.services.ts +96 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.constants.ts +62 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.services.ts +244 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.ts +53 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.types.ts +68 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.utils.ts +100 -0
- package/test/examples/flappy_bird/browser-entry/playback/frame-render/README.md +310 -0
- package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.service.ts +92 -0
- package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.services.ts +272 -0
- package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.types.ts +39 -0
- package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.utils.ts +493 -0
- package/test/examples/flappy_bird/browser-entry/playback/playback.constants.ts +1 -1
- package/test/examples/flappy_bird/browser-entry/playback/playback.frame-render.service.ts +4 -0
- package/test/examples/flappy_bird/browser-entry/playback/playback.snapshot.utils.ts +44 -0
- package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.service.ts +39 -122
- package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.services.ts +272 -0
- package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.types.ts +62 -0
- package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.utils.ts +11 -4
- package/test/examples/flappy_bird/browser-entry/playback/playback.ts +409 -8
- package/test/examples/flappy_bird/browser-entry/playback/playback.types.ts +4 -12
- package/test/examples/flappy_bird/browser-entry/runtime/README.md +235 -0
- package/test/examples/flappy_bird/browser-entry/runtime/runtime.evolution-launch.service.ts +45 -0
- package/test/examples/flappy_bird/browser-entry/runtime/runtime.lifecycle.service.ts +81 -0
- package/test/examples/flappy_bird/browser-entry/runtime/runtime.startup.service.ts +74 -0
- package/test/examples/flappy_bird/browser-entry/runtime/runtime.ts +31 -121
- package/test/examples/flappy_bird/browser-entry/runtime/runtime.types.ts +36 -0
- package/test/examples/flappy_bird/browser-entry/visualization/README.md +557 -0
- package/test/examples/flappy_bird/browser-entry/visualization/visualization.constants.ts +110 -0
- package/test/examples/flappy_bird/browser-entry/visualization/visualization.draw.service.ts +957 -19
- package/test/examples/flappy_bird/browser-entry/visualization/visualization.legend.utils.ts +138 -3
- package/test/examples/flappy_bird/browser-entry/visualization/visualization.topology.utils.ts +3 -27
- package/test/examples/flappy_bird/browser-entry/visualization/visualization.ts +1 -23
- package/test/examples/flappy_bird/browser-entry/worker-channel/README.md +156 -0
- package/test/examples/flappy_bird/constants/README.md +1179 -0
- package/test/examples/flappy_bird/constants/constants.network-view.ts +24 -0
- package/test/examples/flappy_bird/constants/constants.palette.ts +7 -0
- package/test/examples/flappy_bird/constants/constants.starfield.ts +78 -3
- package/test/examples/flappy_bird/environment/README.md +143 -0
- package/test/examples/flappy_bird/environment/environment.observation.utils.ts +1 -19
- package/test/examples/flappy_bird/environment/environment.step.service.ts +3 -66
- package/test/examples/flappy_bird/evaluation/README.md +130 -0
- package/test/examples/flappy_bird/evaluation/evaluation.fitness.utils.ts +1 -1
- package/test/examples/flappy_bird/evaluation/evaluation.rollout.service.ts +5 -375
- package/test/examples/flappy_bird/evaluation/rollout/README.md +291 -0
- package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.constants.ts +30 -0
- package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.service.ts +58 -0
- package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.services.ts +310 -0
- package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.types.ts +56 -0
- package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.utils.ts +368 -0
- package/test/examples/flappy_bird/flappy-evolution-worker/README.md +618 -0
- package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.playback.service.ts +7 -7
- package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.frame.service.ts +364 -0
- package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.types.ts +14 -0
- package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.utils.ts +4 -201
- package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.ts +184 -345
- package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.warm-start.service.ts +291 -0
- package/test/examples/flappy_bird/flappy.simulation.shared.utils.ts +5 -0
- package/test/examples/flappy_bird/simulation-shared/README.md +417 -0
- package/test/examples/flappy_bird/simulation-shared/observation/README.md +183 -0
- package/test/examples/flappy_bird/simulation-shared/observation/observation.features.utils.ts +301 -0
- package/test/examples/flappy_bird/simulation-shared/observation/observation.ts +9 -0
- package/test/examples/flappy_bird/simulation-shared/observation/observation.vector.utils.ts +59 -0
- package/test/examples/flappy_bird/simulation-shared/simulation-shared.observation.utils.ts +5 -403
- package/test/examples/flappy_bird/simulation-shared/simulation-shared.spawn.utils.ts +20 -6
- package/test/examples/flappy_bird/{evaluation/evaluation.statistics.utils.ts → simulation-shared/simulation-shared.statistics.utils.ts} +23 -8
- package/test/examples/flappy_bird/trainer/README.md +563 -0
- package/test/examples/flappy_bird/trainer/evaluation/README.md +199 -0
- package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.constants.ts +9 -0
- package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.services.ts +73 -0
- package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.ts +165 -0
- package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.types.ts +25 -0
- package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.utils.ts +161 -0
- package/test/examples/flappy_bird/trainer/trainer.evaluation.service.ts +13 -0
- package/test/examples/flappy_bird/trainer/trainer.report.service.services.ts +181 -0
- package/test/examples/flappy_bird/trainer/trainer.report.service.ts +126 -0
- package/test/examples/flappy_bird/trainer/trainer.selection.utils.ts +89 -0
- package/test/examples/flappy_bird/trainer/trainer.ts +11 -553
- package/test/examples/flappy_bird/browser-entry/browser-entry.utils.ts +0 -12
- package/test/examples/flappy_bird/environment/environment.ts +0 -7
- package/test/examples/flappy_bird/evaluation/evaluation.ts +0 -7
- package/test/examples/flappy_bird/simulation-shared/simulation-shared.ts +0 -15
- package/test/examples/flappy_bird/trainer/trainer.statistics.utils.ts +0 -78
|
@@ -3,50 +3,16 @@
|
|
|
3
3
|
import { Neat } from '../../../../src/neataptic';
|
|
4
4
|
import Network from '../../../../src/architecture/network';
|
|
5
5
|
import { createXorshift32 } from '../rng';
|
|
6
|
-
import {
|
|
7
|
-
commitObservationMemoryStep,
|
|
8
|
-
resolveFlapDecision,
|
|
9
|
-
resolveObservationVector,
|
|
10
|
-
} from '../browser-entry/browser-entry.observation.utils';
|
|
11
|
-
import {
|
|
12
|
-
createBirdColor,
|
|
13
|
-
resolveDifficultyProfile,
|
|
14
|
-
sampleGapCenterY,
|
|
15
|
-
} from '../browser-entry/browser-entry.spawn.utils';
|
|
16
6
|
import type {
|
|
17
|
-
WorkerHeuristicObservationFeatures,
|
|
18
7
|
WorkerInitMessage,
|
|
19
|
-
WorkerPlaybackFrameSnapshot,
|
|
20
|
-
WorkerPopulationPipe,
|
|
21
8
|
WorkerPlaybackState,
|
|
22
9
|
WorkerRequestMessage,
|
|
23
10
|
WorkerRequestPlaybackStepMessage,
|
|
24
11
|
WorkerResponseMessage,
|
|
12
|
+
WorkerStartPlaybackMessage,
|
|
25
13
|
} from './flappy-evolution-worker.types';
|
|
26
14
|
import { createInitializedWorkerRuntime } from './flappy-evolution-worker.runtime.service';
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
FLAPPY_BIRD_RADIUS_PX,
|
|
30
|
-
FLAPPY_BIRD_X_PX,
|
|
31
|
-
FLAPPY_PIPE_COLLISION_ENTRANCE_EXPAND_PX,
|
|
32
|
-
FLAPPY_PIPE_COLLISION_SIDE_EXPAND_PX,
|
|
33
|
-
FLAPPY_CONTROL_SUBSTEPS_PER_FRAME,
|
|
34
|
-
FLAPPY_ENABLE_RUNTIME_INSTRUMENTATION,
|
|
35
|
-
FLAPPY_FLAP_VELOCITY_PX_PER_FRAME,
|
|
36
|
-
FLAPPY_GRAVITY_PX_PER_FRAME2,
|
|
37
|
-
FLAPPY_MAX_FALL_SPEED_PX_PER_FRAME,
|
|
38
|
-
FLAPPY_PIPE_WIDTH_PX,
|
|
39
|
-
FLAPPY_WORLD_HEIGHT_PX,
|
|
40
|
-
} from '../constants/constants';
|
|
41
|
-
import {
|
|
42
|
-
FLAPPY_WORKER_GEN0_PRETRAIN_BATCH_SIZE,
|
|
43
|
-
FLAPPY_WORKER_GEN0_PRETRAIN_BIAS_NOISE_STDDEV,
|
|
44
|
-
FLAPPY_WORKER_GEN0_PRETRAIN_ITERATIONS,
|
|
45
|
-
FLAPPY_WORKER_GEN0_PRETRAIN_RATE,
|
|
46
|
-
FLAPPY_WORKER_GEN0_PRETRAIN_SAMPLE_COUNT,
|
|
47
|
-
FLAPPY_WORKER_GEN0_PRETRAIN_VISIBLE_WORLD_WIDTH_PX,
|
|
48
|
-
FLAPPY_WORKER_GEN0_PRETRAIN_WEIGHT_NOISE_STDDEV,
|
|
49
|
-
} from './flappy-evolution-worker.constants';
|
|
15
|
+
import { FLAPPY_ENABLE_RUNTIME_INSTRUMENTATION } from '../constants/constants';
|
|
50
16
|
import {
|
|
51
17
|
createWorkerErrorMessage,
|
|
52
18
|
createWorkerErrorMessageFromUnknown,
|
|
@@ -59,21 +25,26 @@ import {
|
|
|
59
25
|
processWorkerPlaybackStep,
|
|
60
26
|
} from './flappy-evolution-worker.playback.service';
|
|
61
27
|
import { createWorkerPlaybackSnapshot } from './flappy-evolution-worker.snapshot.utils';
|
|
62
|
-
import {
|
|
63
|
-
import {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
28
|
+
import { createWorkerPopulationRenderState } from './flappy-evolution-worker.simulation.utils';
|
|
29
|
+
import { stepWorkerPopulationFrame } from './flappy-evolution-worker.simulation.frame.service';
|
|
30
|
+
import { warmStartWorkerGenerationZeroIfNeeded } from './flappy-evolution-worker.warm-start.service';
|
|
31
|
+
|
|
32
|
+
const FLAPPY_WORKER_INITIAL_SEED = 0;
|
|
33
|
+
const FLAPPY_WORKER_INITIAL_WINNER_INDEX = -1;
|
|
34
|
+
|
|
35
|
+
type WorkerMutableRuntimeState = {
|
|
36
|
+
stopped: boolean;
|
|
37
|
+
neatRuntime: Neat | undefined;
|
|
38
|
+
currentPopulation: Network[];
|
|
39
|
+
currentPlaybackState: WorkerPlaybackState | undefined;
|
|
40
|
+
currentPlaybackRng: ReturnType<typeof createXorshift32> | undefined;
|
|
41
|
+
playbackWinnerIndex: number;
|
|
42
|
+
initializationPromise: Promise<void> | undefined;
|
|
43
|
+
workerInitSeed: number;
|
|
44
|
+
generationZeroWarmStartApplied: boolean;
|
|
45
|
+
};
|
|
67
46
|
|
|
68
|
-
|
|
69
|
-
let neatRuntime: Neat | undefined;
|
|
70
|
-
let currentPopulation: Network[] = [];
|
|
71
|
-
let currentPlaybackState: WorkerPlaybackState | undefined;
|
|
72
|
-
let currentPlaybackRng: ReturnType<typeof createXorshift32> | undefined;
|
|
73
|
-
let playbackWinnerIndex = -1;
|
|
74
|
-
let initializationPromise: Promise<void> | undefined;
|
|
75
|
-
let workerInitSeed = 0;
|
|
76
|
-
let generationZeroWarmStartApplied = false;
|
|
47
|
+
const workerMutableRuntimeState = createWorkerMutableRuntimeState();
|
|
77
48
|
|
|
78
49
|
/**
|
|
79
50
|
* Main worker message router.
|
|
@@ -90,50 +61,84 @@ let generationZeroWarmStartApplied = false;
|
|
|
90
61
|
* - `request-playback-step`: advance playback and stream telemetry snapshots.
|
|
91
62
|
* - `stop`: mark worker as stopped (future generation requests fail fast).
|
|
92
63
|
*/
|
|
93
|
-
self.onmessage = (
|
|
94
|
-
|
|
95
|
-
|
|
64
|
+
self.onmessage = createWorkerMessageHandler(workerMutableRuntimeState);
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Creates the mutable worker runtime state container.
|
|
68
|
+
*
|
|
69
|
+
* @returns Mutable worker runtime state.
|
|
70
|
+
*/
|
|
71
|
+
function createWorkerMutableRuntimeState(): WorkerMutableRuntimeState {
|
|
72
|
+
// Step 1: Initialize the worker state with empty runtime and playback fields.
|
|
73
|
+
return {
|
|
74
|
+
stopped: false,
|
|
75
|
+
neatRuntime: undefined,
|
|
76
|
+
currentPopulation: [],
|
|
77
|
+
currentPlaybackState: undefined,
|
|
78
|
+
currentPlaybackRng: undefined,
|
|
79
|
+
playbackWinnerIndex: FLAPPY_WORKER_INITIAL_WINNER_INDEX,
|
|
80
|
+
initializationPromise: undefined,
|
|
81
|
+
workerInitSeed: FLAPPY_WORKER_INITIAL_SEED,
|
|
82
|
+
generationZeroWarmStartApplied: false,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Creates the top-level worker message handler.
|
|
88
|
+
*
|
|
89
|
+
* @param workerMutableRuntimeState - Mutable worker runtime state.
|
|
90
|
+
* @returns Worker message handler.
|
|
91
|
+
*/
|
|
92
|
+
function createWorkerMessageHandler(
|
|
93
|
+
workerMutableRuntimeState: WorkerMutableRuntimeState,
|
|
94
|
+
): (event: MessageEvent<WorkerRequestMessage>) => void {
|
|
95
|
+
// Step 1: Capture the protocol handlers so each message reuses the same stateful callbacks.
|
|
96
|
+
const workerProtocolHandlers = createWorkerProtocolHandlers(
|
|
97
|
+
workerMutableRuntimeState,
|
|
98
|
+
);
|
|
96
99
|
|
|
97
|
-
// Step 2:
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
100
|
+
// Step 2: Return the thin orchestration handler used by `self.onmessage`.
|
|
101
|
+
return (event: MessageEvent<WorkerRequestMessage>): void => {
|
|
102
|
+
const workerMessage = event.data;
|
|
103
|
+
routeWorkerProtocolMessage(workerMessage, workerProtocolHandlers);
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Creates protocol handlers bound to the mutable worker runtime state.
|
|
109
|
+
*
|
|
110
|
+
* @param workerMutableRuntimeState - Mutable worker runtime state.
|
|
111
|
+
* @returns Protocol handler bundle.
|
|
112
|
+
*/
|
|
113
|
+
function createWorkerProtocolHandlers(
|
|
114
|
+
workerMutableRuntimeState: WorkerMutableRuntimeState,
|
|
115
|
+
) {
|
|
116
|
+
// Step 1: Bind each protocol operation to the shared mutable runtime state.
|
|
117
|
+
return {
|
|
118
|
+
markStopped: (): void => {
|
|
119
|
+
workerMutableRuntimeState.stopped = true;
|
|
120
|
+
},
|
|
121
|
+
beginInitialization: (payload: WorkerInitMessage['payload']): void => {
|
|
122
|
+
beginWorkerInitialization(workerMutableRuntimeState, payload);
|
|
101
123
|
},
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
(error: unknown) => {
|
|
105
|
-
postWorkerMessage(createWorkerErrorMessageFromUnknown(error));
|
|
106
|
-
throw error;
|
|
107
|
-
},
|
|
108
|
-
);
|
|
109
|
-
void initializationPromise.catch(() => {
|
|
110
|
-
postWorkerMessage(
|
|
111
|
-
createWorkerErrorMessage(FLAPPY_WORKER_INIT_FAILED_ERROR_MESSAGE),
|
|
112
|
-
);
|
|
113
|
-
});
|
|
124
|
+
beginGenerationRequest: (): void => {
|
|
125
|
+
beginWorkerGenerationRequest(workerMutableRuntimeState);
|
|
114
126
|
},
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
127
|
+
hasPopulation: (): boolean =>
|
|
128
|
+
workerMutableRuntimeState.currentPopulation.length > 0,
|
|
129
|
+
startPlayback: (payload: WorkerStartPlaybackMessage['payload']): void => {
|
|
130
|
+
beginWorkerPlayback(workerMutableRuntimeState, payload);
|
|
119
131
|
},
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
createPopulationRenderState: createWorkerPopulationRenderState,
|
|
127
|
-
});
|
|
128
|
-
currentPlaybackState = nextPlaybackSessionState.currentPlaybackState;
|
|
129
|
-
currentPlaybackRng = nextPlaybackSessionState.currentPlaybackRng;
|
|
130
|
-
playbackWinnerIndex = nextPlaybackSessionState.playbackWinnerIndex;
|
|
132
|
+
hasPlaybackState: (): boolean =>
|
|
133
|
+
workerMutableRuntimeState.currentPlaybackState != null,
|
|
134
|
+
processPlaybackStep: (
|
|
135
|
+
payload: WorkerRequestPlaybackStepMessage['payload'],
|
|
136
|
+
): void => {
|
|
137
|
+
processWorkerPlaybackStepRequest(workerMutableRuntimeState, payload);
|
|
131
138
|
},
|
|
132
|
-
hasPlaybackState: () => currentPlaybackState != null,
|
|
133
|
-
processPlaybackStep,
|
|
134
139
|
postWorkerMessage,
|
|
135
|
-
}
|
|
136
|
-
}
|
|
140
|
+
};
|
|
141
|
+
}
|
|
137
142
|
|
|
138
143
|
/**
|
|
139
144
|
* Initializes the worker-local NEAT runtime used by browser evolution playback.
|
|
@@ -147,13 +152,15 @@ self.onmessage = (event: MessageEvent<WorkerRequestMessage>) => {
|
|
|
147
152
|
* @returns Promise resolved when runtime setup is complete.
|
|
148
153
|
*/
|
|
149
154
|
async function initializeRuntime(
|
|
155
|
+
workerMutableRuntimeState: WorkerMutableRuntimeState,
|
|
150
156
|
initPayload: WorkerInitMessage['payload'],
|
|
151
157
|
): Promise<void> {
|
|
152
158
|
// Step 1: Persist the worker seed so warm-start logic can reuse it deterministically.
|
|
153
|
-
workerInitSeed = initPayload.rngSeed;
|
|
159
|
+
workerMutableRuntimeState.workerInitSeed = initPayload.rngSeed;
|
|
154
160
|
|
|
155
161
|
// Step 2: Build and configure the NEAT runtime controller.
|
|
156
|
-
neatRuntime =
|
|
162
|
+
workerMutableRuntimeState.neatRuntime =
|
|
163
|
+
createInitializedWorkerRuntime(initPayload);
|
|
157
164
|
}
|
|
158
165
|
|
|
159
166
|
/**
|
|
@@ -166,14 +173,23 @@ async function initializeRuntime(
|
|
|
166
173
|
*
|
|
167
174
|
* @returns Promise resolved after generation payload is posted.
|
|
168
175
|
*/
|
|
169
|
-
async function evolveAndPublishGeneration(
|
|
176
|
+
async function evolveAndPublishGeneration(
|
|
177
|
+
workerMutableRuntimeState: WorkerMutableRuntimeState,
|
|
178
|
+
): Promise<void> {
|
|
170
179
|
const generationPayload = await evolveAndBuildGenerationReadyMessage({
|
|
171
|
-
initializationPromise,
|
|
172
|
-
neatRuntime,
|
|
173
|
-
isStopped: () => stopped,
|
|
174
|
-
warmStartGenerationZeroIfNeeded
|
|
180
|
+
initializationPromise: workerMutableRuntimeState.initializationPromise,
|
|
181
|
+
neatRuntime: workerMutableRuntimeState.neatRuntime,
|
|
182
|
+
isStopped: () => workerMutableRuntimeState.stopped,
|
|
183
|
+
warmStartGenerationZeroIfNeeded: (neatController) =>
|
|
184
|
+
warmStartWorkerGenerationZeroIfNeeded(neatController, {
|
|
185
|
+
workerInitSeed: workerMutableRuntimeState.workerInitSeed,
|
|
186
|
+
generationZeroWarmStartApplied:
|
|
187
|
+
workerMutableRuntimeState.generationZeroWarmStartApplied,
|
|
188
|
+
}).then(() => {
|
|
189
|
+
workerMutableRuntimeState.generationZeroWarmStartApplied = true;
|
|
190
|
+
}),
|
|
175
191
|
setCurrentPopulation: (nextPopulation) => {
|
|
176
|
-
currentPopulation = nextPopulation;
|
|
192
|
+
workerMutableRuntimeState.currentPopulation = nextPopulation;
|
|
177
193
|
},
|
|
178
194
|
});
|
|
179
195
|
|
|
@@ -181,263 +197,75 @@ async function evolveAndPublishGeneration(): Promise<void> {
|
|
|
181
197
|
}
|
|
182
198
|
|
|
183
199
|
/**
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
* Educational note:
|
|
187
|
-
* NEAT in this setup starts from cloned copies of one seed architecture.
|
|
188
|
-
* A short supervised warm-up can reduce the "all-random" first-generation
|
|
189
|
-
* behavior while preserving evolutionary search in later generations.
|
|
190
|
-
*
|
|
191
|
-
* Strategy:
|
|
192
|
-
* 1) Build heuristic-labeled synthetic observations.
|
|
193
|
-
* 2) Train one template network quickly.
|
|
194
|
-
* 3) Copy template parameters to each genome with small Gaussian noise.
|
|
195
|
-
*
|
|
196
|
-
* @param neatController - Initialized NEAT runtime.
|
|
197
|
-
* @returns Promise resolved when warm-start decision completes.
|
|
198
|
-
*/
|
|
199
|
-
async function warmStartGenerationZeroIfNeeded(
|
|
200
|
-
neatController: Neat,
|
|
201
|
-
): Promise<void> {
|
|
202
|
-
// Step 1: Exit fast when warm-start is already processed.
|
|
203
|
-
if (generationZeroWarmStartApplied) return;
|
|
204
|
-
|
|
205
|
-
// Step 2: Warm-start only generation 0 to avoid skewing later evolution.
|
|
206
|
-
if (neatController.generation !== 0) {
|
|
207
|
-
generationZeroWarmStartApplied = true;
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// Step 3: Validate population availability.
|
|
212
|
-
const population = neatController.population;
|
|
213
|
-
if (!Array.isArray(population) || population.length === 0) {
|
|
214
|
-
generationZeroWarmStartApplied = true;
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// Step 1: Build a small synthetic dataset labeled by a simple heuristic.
|
|
219
|
-
// The goal is NOT to solve Flappy here, only to avoid a totally random first generation.
|
|
220
|
-
const warmStartRng = createXorshift32(workerInitSeed ^ 0x9e37_79b9);
|
|
221
|
-
const trainingSet = buildHeuristicPretrainSet(
|
|
222
|
-
warmStartRng,
|
|
223
|
-
FLAPPY_WORKER_GEN0_PRETRAIN_SAMPLE_COUNT,
|
|
224
|
-
);
|
|
225
|
-
|
|
226
|
-
// Step 2: Train a single template network (fast), then seed the whole population from it.
|
|
227
|
-
const templateNetwork = population[0]?.clone();
|
|
228
|
-
if (!templateNetwork) {
|
|
229
|
-
generationZeroWarmStartApplied = true;
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
try {
|
|
234
|
-
templateNetwork.train(trainingSet, {
|
|
235
|
-
iterations: FLAPPY_WORKER_GEN0_PRETRAIN_ITERATIONS,
|
|
236
|
-
rate: FLAPPY_WORKER_GEN0_PRETRAIN_RATE,
|
|
237
|
-
batchSize: FLAPPY_WORKER_GEN0_PRETRAIN_BATCH_SIZE,
|
|
238
|
-
optimizer: 'adam',
|
|
239
|
-
// Keep the training loop simple and deterministic.
|
|
240
|
-
mixedPrecision: false,
|
|
241
|
-
});
|
|
242
|
-
} catch {
|
|
243
|
-
// If training fails for any reason (e.g., incompatible topology), fall back to pure noise seeding.
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// Step 3: Copy trained weights/biases into each genome with small noise for diversity.
|
|
247
|
-
for (const genome of population) {
|
|
248
|
-
applyTemplateWeightsWithNoise(genome, templateNetwork, warmStartRng, {
|
|
249
|
-
weightStdDev: FLAPPY_WORKER_GEN0_PRETRAIN_WEIGHT_NOISE_STDDEV,
|
|
250
|
-
biasStdDev: FLAPPY_WORKER_GEN0_PRETRAIN_BIAS_NOISE_STDDEV,
|
|
251
|
-
});
|
|
252
|
-
(genome as unknown as { score?: number }).score = undefined;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
generationZeroWarmStartApplied = true;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* Builds synthetic supervised samples for generation-0 behavior cloning.
|
|
260
|
-
*
|
|
261
|
-
* Educational note:
|
|
262
|
-
* Samples are generated from plausible Flappy states and passed through the
|
|
263
|
-
* exact observation encoder used during runtime. This keeps feature semantics
|
|
264
|
-
* aligned between pretraining and live simulation.
|
|
200
|
+
* Begins worker initialization and captures asynchronous failures.
|
|
265
201
|
*
|
|
266
|
-
* @param
|
|
267
|
-
* @param
|
|
268
|
-
* @returns
|
|
202
|
+
* @param workerMutableRuntimeState - Mutable worker runtime state.
|
|
203
|
+
* @param initPayload - Initialization payload.
|
|
204
|
+
* @returns Nothing.
|
|
269
205
|
*/
|
|
270
|
-
function
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
):
|
|
274
|
-
// Step 1:
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
const gapHalfPx = pipeGapPx * 0.5;
|
|
283
|
-
|
|
284
|
-
const birdYPx = rng.nextFloat01() * FLAPPY_WORLD_HEIGHT_PX;
|
|
285
|
-
const velocityYPxPerFrame =
|
|
286
|
-
(rng.nextFloat01() * 2 - 1) * FLAPPY_MAX_FALL_SPEED_PX_PER_FRAME;
|
|
287
|
-
|
|
288
|
-
const pipeXMinPx = FLAPPY_BIRD_X_PX + 40;
|
|
289
|
-
const pipeXMaxPx =
|
|
290
|
-
FLAPPY_BIRD_X_PX +
|
|
291
|
-
FLAPPY_WORKER_GEN0_PRETRAIN_VISIBLE_WORLD_WIDTH_PX * 0.92;
|
|
292
|
-
const pipeXSamplePx =
|
|
293
|
-
pipeXMinPx + rng.nextFloat01() * Math.max(1, pipeXMaxPx - pipeXMinPx);
|
|
294
|
-
|
|
295
|
-
const minGapCenterYPx = gapHalfPx;
|
|
296
|
-
const maxGapCenterYPx = Math.max(
|
|
297
|
-
minGapCenterYPx,
|
|
298
|
-
FLAPPY_WORLD_HEIGHT_PX - gapHalfPx,
|
|
299
|
-
);
|
|
300
|
-
const gapCenterYPx =
|
|
301
|
-
minGapCenterYPx + rng.nextFloat01() * (maxGapCenterYPx - minGapCenterYPx);
|
|
302
|
-
|
|
303
|
-
const pipes: WorkerPopulationPipe[] = [
|
|
304
|
-
{
|
|
305
|
-
id: 1,
|
|
306
|
-
xPx: pipeXSamplePx,
|
|
307
|
-
gapCenterYPx,
|
|
308
|
-
gapSizePx: pipeGapPx,
|
|
309
|
-
},
|
|
310
|
-
];
|
|
311
|
-
|
|
312
|
-
const observationMemoryState = createSharedObservationMemoryState();
|
|
313
|
-
const observation = resolveObservationVector(
|
|
314
|
-
birdYPx,
|
|
315
|
-
velocityYPxPerFrame,
|
|
316
|
-
pipes,
|
|
317
|
-
FLAPPY_WORKER_GEN0_PRETRAIN_VISIBLE_WORLD_WIDTH_PX,
|
|
318
|
-
FLAPPY_WORLD_HEIGHT_PX,
|
|
319
|
-
difficultyProfile,
|
|
320
|
-
difficultyProfile.pipeSpawnIntervalFrames,
|
|
321
|
-
observationMemoryState,
|
|
322
|
-
);
|
|
206
|
+
function beginWorkerInitialization(
|
|
207
|
+
workerMutableRuntimeState: WorkerMutableRuntimeState,
|
|
208
|
+
initPayload: WorkerInitMessage['payload'],
|
|
209
|
+
): void {
|
|
210
|
+
// Step 1: Start initialization and retain the promise for later generation requests.
|
|
211
|
+
workerMutableRuntimeState.initializationPromise = initializeRuntime(
|
|
212
|
+
workerMutableRuntimeState,
|
|
213
|
+
initPayload,
|
|
214
|
+
).catch((error: unknown) => {
|
|
215
|
+
postWorkerMessage(createWorkerErrorMessageFromUnknown(error));
|
|
216
|
+
throw error;
|
|
217
|
+
});
|
|
323
218
|
|
|
324
|
-
|
|
325
|
-
|
|
219
|
+
// Step 2: Emit a stable init-failed error if the initialization promise rejects.
|
|
220
|
+
void workerMutableRuntimeState.initializationPromise.catch(() => {
|
|
221
|
+
postWorkerMessage(
|
|
222
|
+
createWorkerErrorMessage(FLAPPY_WORKER_INIT_FAILED_ERROR_MESSAGE),
|
|
326
223
|
);
|
|
327
|
-
|
|
328
|
-
input: observation.observationVector,
|
|
329
|
-
output: shouldFlap ? [0, 1] : [1, 0],
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
// Step 3: Return immutable training pairs consumed by `Network.train`.
|
|
334
|
-
return trainingSet;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
/**
|
|
338
|
-
* Heuristic teacher policy used to label synthetic pretraining samples.
|
|
339
|
-
*
|
|
340
|
-
* Educational note:
|
|
341
|
-
* The teacher is intentionally simple and interpretable, acting as a rough
|
|
342
|
-
* "stay near next gap center" controller. The objective is biasing the initial
|
|
343
|
-
* policy away from chaotic behavior, not producing expert trajectories.
|
|
344
|
-
*
|
|
345
|
-
* @param features - Structured observation features for one synthetic state.
|
|
346
|
-
* @returns True when the teacher says "flap".
|
|
347
|
-
*/
|
|
348
|
-
function resolveHeuristicTeacherFlapDecision(
|
|
349
|
-
features: WorkerHeuristicObservationFeatures,
|
|
350
|
-
): boolean {
|
|
351
|
-
// Heuristic intent:
|
|
352
|
-
// - If the bird is below the upcoming gap center, flap to correct upward.
|
|
353
|
-
// - Avoid spamming flap when already moving upward quickly.
|
|
354
|
-
// - Prefer corrections closer to the pipe (or when urgency is high).
|
|
355
|
-
const isBelowNextGapCenter = features.normalizedDeltaToNextGap > 0.035;
|
|
356
|
-
const isNotAlreadyRisingFast = features.normalizedVelocity > -0.25;
|
|
357
|
-
const isNearGapEntry = features.normalizedFramesToGapEntry < 0.8;
|
|
358
|
-
const isUrgent = features.normalizedEntryUrgency > 0.18;
|
|
359
|
-
|
|
360
|
-
return (
|
|
361
|
-
isBelowNextGapCenter &&
|
|
362
|
-
isNotAlreadyRisingFast &&
|
|
363
|
-
(isNearGapEntry || isUrgent)
|
|
364
|
-
);
|
|
224
|
+
});
|
|
365
225
|
}
|
|
366
226
|
|
|
367
227
|
/**
|
|
368
|
-
*
|
|
228
|
+
* Begins one asynchronous generation request and captures failures.
|
|
369
229
|
*
|
|
370
|
-
*
|
|
371
|
-
* Copying one trained template without noise would collapse diversity. Adding
|
|
372
|
-
* mild deterministic jitter keeps the population near a useful baseline while
|
|
373
|
-
* preserving variation for selection and mutation.
|
|
374
|
-
*
|
|
375
|
-
* @param genome - Target genome to mutate in-place.
|
|
376
|
-
* @param template - Trained template source network.
|
|
377
|
-
* @param rng - Deterministic random source for noise sampling.
|
|
378
|
-
* @param noise - Standard deviations for weight and bias perturbations.
|
|
230
|
+
* @param workerMutableRuntimeState - Mutable worker runtime state.
|
|
379
231
|
* @returns Nothing.
|
|
380
232
|
*/
|
|
381
|
-
function
|
|
382
|
-
|
|
383
|
-
template: Network,
|
|
384
|
-
rng: ReturnType<typeof createXorshift32>,
|
|
385
|
-
noise: { weightStdDev: number; biasStdDev: number },
|
|
233
|
+
function beginWorkerGenerationRequest(
|
|
234
|
+
workerMutableRuntimeState: WorkerMutableRuntimeState,
|
|
386
235
|
): void {
|
|
387
|
-
// Step 1:
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
const genomeNodes = genome.nodes;
|
|
393
|
-
const templateNodes = template.nodes;
|
|
394
|
-
const nodeCopyCount = Math.min(genomeNodes.length, templateNodes.length);
|
|
395
|
-
for (let nodeIndex = 0; nodeIndex < nodeCopyCount; nodeIndex++) {
|
|
396
|
-
const templateBias = templateNodes[nodeIndex]?.bias ?? 0;
|
|
397
|
-
genomeNodes[nodeIndex].bias =
|
|
398
|
-
templateBias + sampleGaussian(rng) * biasStdDev;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
// Step 3: Copy connection weights with additive Gaussian noise.
|
|
402
|
-
const genomeConnections = genome.connections;
|
|
403
|
-
const templateConnections = template.connections;
|
|
404
|
-
const connectionCopyCount = Math.min(
|
|
405
|
-
genomeConnections.length,
|
|
406
|
-
templateConnections.length,
|
|
236
|
+
// Step 1: Run the generation pipeline and publish worker errors on failure.
|
|
237
|
+
void evolveAndPublishGeneration(workerMutableRuntimeState).catch(
|
|
238
|
+
(error: unknown) => {
|
|
239
|
+
postWorkerMessage(createWorkerErrorMessageFromUnknown(error));
|
|
240
|
+
},
|
|
407
241
|
);
|
|
408
|
-
for (
|
|
409
|
-
let connectionIndex = 0;
|
|
410
|
-
connectionIndex < connectionCopyCount;
|
|
411
|
-
connectionIndex++
|
|
412
|
-
) {
|
|
413
|
-
const templateWeight = templateConnections[connectionIndex]?.weight ?? 0;
|
|
414
|
-
genomeConnections[connectionIndex].weight =
|
|
415
|
-
templateWeight + sampleGaussian(rng) * weightStdDev;
|
|
416
|
-
}
|
|
417
242
|
}
|
|
418
243
|
|
|
419
244
|
/**
|
|
420
|
-
*
|
|
245
|
+
* Begins a new playback session from the current evolved population.
|
|
421
246
|
*
|
|
422
|
-
*
|
|
423
|
-
*
|
|
424
|
-
*
|
|
425
|
-
* zero while still occasionally exploring larger offsets.
|
|
426
|
-
*
|
|
427
|
-
* @param rng - Deterministic random source.
|
|
428
|
-
* @returns One approximately standard-normal random value.
|
|
247
|
+
* @param workerMutableRuntimeState - Mutable worker runtime state.
|
|
248
|
+
* @param payload - Playback start payload.
|
|
249
|
+
* @returns Nothing.
|
|
429
250
|
*/
|
|
430
|
-
function
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
const
|
|
251
|
+
function beginWorkerPlayback(
|
|
252
|
+
workerMutableRuntimeState: WorkerMutableRuntimeState,
|
|
253
|
+
payload: { visibleWorldWidthPx: number; visibleWorldHeightPx: number },
|
|
254
|
+
): void {
|
|
255
|
+
// Step 1: Create the next playback session from the current population snapshot.
|
|
256
|
+
const nextPlaybackSessionState = beginWorkerPlaybackSession({
|
|
257
|
+
currentPopulation: workerMutableRuntimeState.currentPopulation,
|
|
258
|
+
payload,
|
|
259
|
+
createPopulationRenderState: createWorkerPopulationRenderState,
|
|
260
|
+
});
|
|
436
261
|
|
|
437
|
-
// Step 2:
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
262
|
+
// Step 2: Persist the next playback state, RNG, and winner index.
|
|
263
|
+
workerMutableRuntimeState.currentPlaybackState =
|
|
264
|
+
nextPlaybackSessionState.currentPlaybackState;
|
|
265
|
+
workerMutableRuntimeState.currentPlaybackRng =
|
|
266
|
+
nextPlaybackSessionState.currentPlaybackRng;
|
|
267
|
+
workerMutableRuntimeState.playbackWinnerIndex =
|
|
268
|
+
nextPlaybackSessionState.playbackWinnerIndex;
|
|
441
269
|
}
|
|
442
270
|
|
|
443
271
|
/**
|
|
@@ -451,30 +279,41 @@ function sampleGaussian(rng: ReturnType<typeof createXorshift32>): number {
|
|
|
451
279
|
* @param playbackStepPayload - Host-selected simulation-step budget and viewport.
|
|
452
280
|
* @returns Nothing.
|
|
453
281
|
*/
|
|
454
|
-
function
|
|
282
|
+
function processWorkerPlaybackStepRequest(
|
|
283
|
+
workerMutableRuntimeState: WorkerMutableRuntimeState,
|
|
455
284
|
playbackStepPayload: WorkerRequestPlaybackStepMessage['payload'],
|
|
456
285
|
): void {
|
|
457
|
-
|
|
286
|
+
// Step 1: Guard against playback-step requests before playback state exists.
|
|
287
|
+
if (
|
|
288
|
+
!workerMutableRuntimeState.currentPlaybackState ||
|
|
289
|
+
!workerMutableRuntimeState.currentPlaybackRng
|
|
290
|
+
) {
|
|
458
291
|
throw new Error(
|
|
459
292
|
'Playback random source is unavailable. Start playback first.',
|
|
460
293
|
);
|
|
461
294
|
}
|
|
462
295
|
|
|
296
|
+
// Step 2: Advance playback and build the next compact snapshot payload.
|
|
463
297
|
const nextPlaybackStepState = processWorkerPlaybackStep({
|
|
464
298
|
playbackStepPayload,
|
|
465
|
-
currentPlaybackState,
|
|
466
|
-
currentPlaybackRng,
|
|
467
|
-
currentPopulation,
|
|
468
|
-
neatRuntime,
|
|
299
|
+
currentPlaybackState: workerMutableRuntimeState.currentPlaybackState,
|
|
300
|
+
currentPlaybackRng: workerMutableRuntimeState.currentPlaybackRng,
|
|
301
|
+
currentPopulation: workerMutableRuntimeState.currentPopulation,
|
|
302
|
+
neatRuntime: workerMutableRuntimeState.neatRuntime,
|
|
469
303
|
stepPopulationFrame: stepWorkerPopulationFrame,
|
|
470
304
|
createPlaybackSnapshot: createWorkerPlaybackSnapshot,
|
|
471
305
|
postWorkerMessage,
|
|
472
306
|
});
|
|
473
307
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
308
|
+
// Step 3: Persist the advanced playback state for the next host request.
|
|
309
|
+
workerMutableRuntimeState.currentPlaybackState =
|
|
310
|
+
nextPlaybackStepState.currentPlaybackState;
|
|
311
|
+
workerMutableRuntimeState.currentPlaybackRng =
|
|
312
|
+
nextPlaybackStepState.currentPlaybackRng;
|
|
313
|
+
workerMutableRuntimeState.currentPopulation =
|
|
314
|
+
nextPlaybackStepState.currentPopulation;
|
|
315
|
+
workerMutableRuntimeState.playbackWinnerIndex =
|
|
316
|
+
nextPlaybackStepState.playbackWinnerIndex;
|
|
478
317
|
}
|
|
479
318
|
|
|
480
319
|
/**
|