@descix/frqtl-node 0.0.0-stage → 0.6.0-p0.2

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 (218) hide show
  1. package/CLAUDE.md +87 -0
  2. package/LICENSE.md +664 -0
  3. package/README.md +84 -2
  4. package/dist/dist-manifest.json +218 -0
  5. package/dist/eyes/index.js +109 -0
  6. package/dist/fat/pkg-node/egpt_wasm.js +1277 -0
  7. package/dist/fat/pkg-node/egpt_wasm_bg.wasm +0 -0
  8. package/dist/fat/pkg-node/package.json +12 -0
  9. package/dist/frqtl/assets/vendor/chroma.mjs +64 -0
  10. package/dist/frqtl/compat/boot-node.js +34 -0
  11. package/dist/frqtl/compat/engine.js +127 -0
  12. package/dist/frqtl/compat/package-root.js +24 -0
  13. package/dist/frqtl/compat/providers/wasm-engine.js +2499 -0
  14. package/dist/frqtl/compat/providers/wasm-load-browser.js +134 -0
  15. package/dist/frqtl/compat/providers/wasm-load-node.js +59 -0
  16. package/dist/frqtl/compat/renderer/FieldBuilder.js +145 -0
  17. package/dist/frqtl/compat/renderer/Filters.js +163 -0
  18. package/dist/frqtl/compat/renderer/RenderFamily.js +84 -0
  19. package/dist/frqtl/compat/renderer/RenderMesh.js +99 -0
  20. package/dist/frqtl/compat/renderer/RenderShape.js +154 -0
  21. package/dist/frqtl/compat/renderer/camera2d-geometry.js +183 -0
  22. package/dist/frqtl/compat/renderer/captureStill-common.js +258 -0
  23. package/dist/frqtl/compat/renderer/display-slot.js +96 -0
  24. package/dist/frqtl/compat/renderer/lo-drawn-center.js +231 -0
  25. package/dist/frqtl/compat/renderer/orbit-bag.js +216 -0
  26. package/dist/frqtl/compat/renderer/providers/godrays-layer.js +213 -0
  27. package/dist/frqtl/compat/renderer/providers/index.js +22 -0
  28. package/dist/frqtl/compat/renderer/providers/p5-provider.js +861 -0
  29. package/dist/frqtl/compat/renderer/providers/three-camera-contract.js +160 -0
  30. package/dist/frqtl/compat/renderer/providers/three-camera-geometry.js +571 -0
  31. package/dist/frqtl/compat/renderer/providers/three-provider.js +2470 -0
  32. package/dist/frqtl/compat/renderer/renderCapabilities-common.js +186 -0
  33. package/dist/frqtl/compat/renderer/renderer-provider-contract.js +238 -0
  34. package/dist/frqtl/compat/renderer/unprojectStill.js +172 -0
  35. package/dist/frqtl/compat/vendor.js +196 -0
  36. package/dist/frqtl/node-entry.js +17 -0
  37. package/dist/frqtl/objects/FrqtlApp.js +2920 -0
  38. package/dist/frqtl/objects/ObjectFactory.js +296 -0
  39. package/dist/frqtl/objects/RecipeContext.js +322 -0
  40. package/dist/frqtl/objects/collectors/DataCollector.js +116 -0
  41. package/dist/frqtl/objects/constants/WallBehaviors.js +178 -0
  42. package/dist/frqtl/objects/geometry/SlabFace.js +258 -0
  43. package/dist/frqtl/objects/instruments/capture-host.js +453 -0
  44. package/dist/frqtl/objects/instruments/capture.js +710 -0
  45. package/dist/frqtl/objects/instruments/hosted-eyes.js +984 -0
  46. package/dist/frqtl/objects/kinds-entry.js +14 -0
  47. package/dist/frqtl/objects/kinds.js +190 -0
  48. package/dist/frqtl/objects/objects/Box.js +273 -0
  49. package/dist/frqtl/objects/objects/Bullet.js +155 -0
  50. package/dist/frqtl/objects/objects/CircuitGate.js +380 -0
  51. package/dist/frqtl/objects/objects/CircuitProbe.js +214 -0
  52. package/dist/frqtl/objects/objects/DirectedTunnel.js +411 -0
  53. package/dist/frqtl/objects/objects/EgptFractal.js +164 -0
  54. package/dist/frqtl/objects/objects/LightSource.js +351 -0
  55. package/dist/frqtl/objects/objects/QuantumEmitter.js +760 -0
  56. package/dist/frqtl/objects/objects/Tube.js +471 -0
  57. package/dist/frqtl/objects/objects/absorbRadiation.js +309 -0
  58. package/dist/frqtl/objects/objects/actionCompiler.js +1747 -0
  59. package/dist/frqtl/objects/objects/controlAction.js +89 -0
  60. package/dist/frqtl/objects/objects/controlBind.js +278 -0
  61. package/dist/frqtl/objects/objects/directedRedirectProgram.js +120 -0
  62. package/dist/frqtl/objects/objects/emitterProgram.js +209 -0
  63. package/dist/frqtl/objects/objects/frqtl-control-slider.js +197 -0
  64. package/dist/frqtl/objects/objects/frqtl-control-sync.js +272 -0
  65. package/dist/frqtl/objects/objects/frqtl-control-widgets.js +219 -0
  66. package/dist/frqtl/objects/objects/frqtl-control-write-queue.js +174 -0
  67. package/dist/frqtl/objects/objects/makeControlsForObject.js +820 -0
  68. package/dist/frqtl/objects/objects/makeControlsForRenderSurface.js +161 -0
  69. package/dist/frqtl/objects/objects/slitLinerScatter.js +261 -0
  70. package/dist/frqtl/objects/objects/sustainedSource.js +298 -0
  71. package/dist/frqtl/objects/objects/tagger.js +228 -0
  72. package/dist/frqtl/objects/schema/engine-scopes.js +468 -0
  73. package/dist/frqtl/objects/schema/index.js +256 -0
  74. package/dist/frqtl/objects/schema/scopes.js +457 -0
  75. package/dist/frqtl/objects/schema/validate-descriptor.js +49 -0
  76. package/dist/frqtl/objects/schema/valueNormalizer.js +366 -0
  77. package/dist/frqtl/objects/setup/_collisionMatrixLanes.js +66 -0
  78. package/dist/frqtl/objects/setup/_setupOptions.js +118 -0
  79. package/dist/frqtl/objects/setup/_worldInit.js +162 -0
  80. package/dist/frqtl/objects/setup/setupBlackbodySubstrate.js +242 -0
  81. package/dist/frqtl/objects/setup/setupCircuitBasic.js +447 -0
  82. package/dist/frqtl/objects/setup/setupCollisionMatrix.js +188 -0
  83. package/dist/frqtl/objects/setup/setupConeEmitter3D.js +250 -0
  84. package/dist/frqtl/objects/setup/setupDoubleSlit.js +326 -0
  85. package/dist/frqtl/objects/setup/setupDoubleSlit_Laser.js +229 -0
  86. package/dist/frqtl/objects/setup/setupEmpty.js +59 -0
  87. package/dist/frqtl/objects/setup/setupFxSmoke.js +209 -0
  88. package/dist/frqtl/objects/setup/setupG1Race.js +80 -0
  89. package/dist/frqtl/objects/setup/setupG2Sweep.js +89 -0
  90. package/dist/frqtl/objects/setup/setupG3Collide.js +177 -0
  91. package/dist/frqtl/objects/setup/setupLightSourceLab.js +277 -0
  92. package/dist/frqtl/objects/setup/setupOscillator.js +68 -0
  93. package/dist/frqtl/objects/setup/setupParticleWalk.js +93 -0
  94. package/dist/frqtl/objects/setup/setupParticleWalk3D.js +133 -0
  95. package/dist/frqtl/objects/setup/setupSphereEmitter3D.js +1258 -0
  96. package/dist/frqtl/objects/setup/setupTraceCircuit.js +239 -0
  97. package/dist/frqtl/objects/setup/setupTunnelLab.js +240 -0
  98. package/dist/frqtl/objects/setup/setupTunnelPointExit.js +306 -0
  99. package/dist/frqtl/objects/setup/setupWaveInterference.js +177 -0
  100. package/dist/frqtl/objects/v1-replacements.js +29 -0
  101. package/dist/frqtl/package-core.js +23 -0
  102. package/dist/frqtl/parts/CameraControls.js +643 -0
  103. package/dist/frqtl/parts/CameraPath.js +575 -0
  104. package/dist/frqtl/parts/CollisionActions.js +34 -0
  105. package/dist/frqtl/parts/CollisionTypes.js +30 -0
  106. package/dist/frqtl/parts/DetectorWall.js +496 -0
  107. package/dist/frqtl/parts/FrqtlControlOverlay.js +227 -0
  108. package/dist/frqtl/parts/FrqtlControlsPanel.js +415 -0
  109. package/dist/frqtl/parts/FrqtlVision.js +818 -0
  110. package/dist/frqtl/parts/GraphingDetectorWall.js +489 -0
  111. package/dist/frqtl/parts/LargeObject.js +405 -0
  112. package/dist/frqtl/parts/LightColor.js +255 -0
  113. package/dist/frqtl/parts/LiveChart.js +285 -0
  114. package/dist/frqtl/parts/LogicGate.js +717 -0
  115. package/dist/frqtl/parts/OvenBox.js +611 -0
  116. package/dist/frqtl/parts/PointSource.js +762 -0
  117. package/dist/frqtl/parts/Rectangle.js +200 -0
  118. package/dist/frqtl/parts/SlitLightSource.js +234 -0
  119. package/dist/frqtl/parts/SlitScreen.js +628 -0
  120. package/dist/frqtl/parts/SphereEmitter.js +946 -0
  121. package/dist/frqtl/parts/Trace.js +508 -0
  122. package/dist/frqtl/parts/Tunnel.js +1057 -0
  123. package/dist/frqtl/parts/Wall.js +1211 -0
  124. package/dist/frqtl/parts/index.js +33 -0
  125. package/dist/frqtl/scenes/absorbing-wall-3d.js +33 -0
  126. package/dist/frqtl/scenes/absorbing-wall.js +32 -0
  127. package/dist/frqtl/scenes/atomic-model.js +88 -0
  128. package/dist/frqtl/scenes/big-bang.js +46 -0
  129. package/dist/frqtl/scenes/blackbody.js +81 -0
  130. package/dist/frqtl/scenes/circuit-sat.js +127 -0
  131. package/dist/frqtl/scenes/collision-matrix-3d.js +107 -0
  132. package/dist/frqtl/scenes/counting-wall-3d.js +36 -0
  133. package/dist/frqtl/scenes/counting-wall.js +38 -0
  134. package/dist/frqtl/scenes/double-slit.js +31 -0
  135. package/dist/frqtl/scenes/dse-one-emitter.js +196 -0
  136. package/dist/frqtl/scenes/dse-one-slit.js +114 -0
  137. package/dist/frqtl/scenes/dse-photoelectric.js +70 -0
  138. package/dist/frqtl/scenes/dse-tunnel-rebuild.js +243 -0
  139. package/dist/frqtl/scenes/dse-two-emitters.js +196 -0
  140. package/dist/frqtl/scenes/dse-two-slits.js +132 -0
  141. package/dist/frqtl/scenes/empty.js +14 -0
  142. package/dist/frqtl/scenes/laser-buildup.js +49 -0
  143. package/dist/frqtl/scenes/mirror-3d.js +56 -0
  144. package/dist/frqtl/scenes/mirror-route.js +140 -0
  145. package/dist/frqtl/scenes/mirror.js +38 -0
  146. package/dist/frqtl/scenes/omni-3d.js +27 -0
  147. package/dist/frqtl/scenes/omni-source.js +22 -0
  148. package/dist/frqtl/scenes/self-interference.js +39 -0
  149. package/dist/frqtl/scenes/smoking-gun.js +122 -0
  150. package/dist/frqtl/scenes/straight-walk.js +22 -0
  151. package/dist/frqtl/scenes/sun.js +39 -0
  152. package/dist/frqtl/scenes/two-source.js +37 -0
  153. package/dist/frqtl/scenes/wave.js +26 -0
  154. package/dist/shim/bundle/frqnb.js +112 -0
  155. package/dist/shim/bundle/index.js +121 -0
  156. package/dist/shim/bundle/indexHtml.js +107 -0
  157. package/dist/shim/bundle/manifest.js +95 -0
  158. package/dist/shim/bundle/zip.js +243 -0
  159. package/dist/shim/bus.js +67 -0
  160. package/dist/shim/controls/index.js +627 -0
  161. package/dist/shim/controls/registry.js +274 -0
  162. package/dist/shim/engine/artifact-shell.js +211 -0
  163. package/dist/shim/engine/boot-phases.js +44 -0
  164. package/dist/shim/engine/engine-stack-boot.js +59 -0
  165. package/dist/shim/engine/router.js +690 -0
  166. package/dist/shim/experiment-frame/index.js +296 -0
  167. package/dist/shim/expr/ast-schema.js +369 -0
  168. package/dist/shim/field-descriptor/index.js +325 -0
  169. package/dist/shim/frame-data/index.js +224 -0
  170. package/dist/shim/index.js +67 -0
  171. package/dist/shim/notebook/canvas-guard.js +82 -0
  172. package/dist/shim/notebook/catalog.js +35 -0
  173. package/dist/shim/notebook/format.js +736 -0
  174. package/dist/shim/notebook/frqtl-setups-importmap.js +81 -0
  175. package/dist/shim/notebook/kernel.js +671 -0
  176. package/dist/shim/notebook/knob.js +150 -0
  177. package/dist/shim/notebook/module-resolver.js +260 -0
  178. package/dist/shim/notebook/notebook-knobs.js +65 -0
  179. package/dist/shim/notebook/produced-bindings.js +67 -0
  180. package/dist/shim/notebook/realm-registry.js +121 -0
  181. package/dist/shim/notebook/realm-transport.js +73 -0
  182. package/dist/shim/notebook/setup-builder.js +507 -0
  183. package/dist/shim/notebook/store.js +159 -0
  184. package/dist/shim/notebook/vendor-importmap.js +134 -0
  185. package/dist/shim/notebook/view-builder.js +189 -0
  186. package/dist/shim/notebook/view-ctx.js +100 -0
  187. package/dist/shim/notebook/view-handle.js +202 -0
  188. package/dist/shim/notebook/warmup.js +102 -0
  189. package/dist/shim/package.json +4 -0
  190. package/dist/shim/page-params/index.js +213 -0
  191. package/dist/shim/project/identity.js +112 -0
  192. package/dist/shim/project/index.js +19 -0
  193. package/dist/shim/project/link.js +402 -0
  194. package/dist/shim/project/node-specifier-hook.mjs +35 -0
  195. package/dist/shim/project/register-node.mjs +17 -0
  196. package/dist/shim/project/specifiers.js +106 -0
  197. package/dist/shim/registry/copy-gate.js +110 -0
  198. package/dist/shim/registry/exhibits.js +455 -0
  199. package/dist/shim/registry/experiments.js +215 -0
  200. package/dist/shim/registry/index.js +19 -0
  201. package/dist/shim/registry/scene-source.js +157 -0
  202. package/dist/shim/registry/walkthrough.js +804 -0
  203. package/dist/shim/render/capture-envelope.js +279 -0
  204. package/dist/shim/render/heat-colormap.js +92 -0
  205. package/dist/shim/render/render-stages.js +855 -0
  206. package/dist/shim/render/sun-look.js +33 -0
  207. package/dist/shim/render-state/apply.js +262 -0
  208. package/dist/shim/render-state/index.js +74 -0
  209. package/dist/shim/rpc/index.js +207 -0
  210. package/dist/shim/runtime/index.js +1023 -0
  211. package/dist/shim/storage/boot.js +69 -0
  212. package/dist/shim/storage/index.js +169 -0
  213. package/dist/shim/storage/local-storage-provider.js +230 -0
  214. package/dist/shim/storage/make-namespace-store.js +132 -0
  215. package/dist/shim/storage/modules.js +249 -0
  216. package/dist/shim/storage/projects.js +150 -0
  217. package/llms.txt +12 -0
  218. package/package.json +63 -4
@@ -0,0 +1,49 @@
1
+ /* Copyright 2023-2026 by Essam Abadir */
2
+
3
+ /**
4
+ * SCENE — 4B · Laser Build-Up
5
+ *
6
+ * A sketch file: the WHOLE scene as one ES module, `export default function buildExperiment(exp)`. The world
7
+ * (its co-init call, `exp.createCanvas` / `exp.createScene` — the one place its size is written),
8
+ * the parts (`exp.addObject`) and the render intent are all here; the sugar
9
+ * objects, renderer and engine are imports. Registered by lib/shim/registry/walkthrough.js
10
+ * (rung r4b-laser-buildup).
11
+ */
12
+
13
+ // LASER BUILD-UP (D4) — the three
14
+ // components of a laser assembled one at a time on top of the earlier Light Lab rungs:
15
+ // 1. a GAIN SOURCE — the hemisphere emitter (rung 3's omni source, restricted forward)
16
+ // 2. a RESONANT BORE — the directed corridor, which re-aims every wall hit forward
17
+ // 3. an OUTPUT COUPLER — the exit gate, optionally collapsing the mouth to a point and
18
+ // optionally re-phase-locking what leaves it
19
+ // The two exit flags are INDEPENDENT and both live, which is what lets the rung separate
20
+ // "does the point source matter?" from "does coherence matter?".
21
+ //
22
+ // SINGLE AUTHORITY: the emitter + tunnel configs come from `setupTunnelPointExit.sceneSpec()`
23
+ // — the SAME pure function the standalone `tunnel-point-exit` page's factory consumes. The
24
+ // rung is the addObject form (so STUDIO can select and edit the objects); the page is the
25
+ // slider-driven form. They share the numbers rather than each hand-carrying a copy.
26
+
27
+ import { SphereEmitter, Tunnel } from '@descix/frqtl-web/parts';
28
+
29
+ export default function buildExperiment(exp) {
30
+ // Laser Build-Up — gain source + resonant bore + output coupler.
31
+ // Geometry and per-leaf creation conditions come from the ONE scene-spec authority,
32
+ // Tunnel.pointExitSpec() (setupTunnelPointExit.sceneSpec), so this rung and the standalone page cannot drift.
33
+ var W = 600, H = 400; // THE WORLD this scene states (its co-init call below)
34
+ var spec = Tunnel.pointExitSpec({
35
+ canvasW: W, canvasH: H,
36
+ tunnelLength: 240, // REBUILD-class: corridor geometry, re-authored not dragged
37
+ wavelengthScale: 16, // eff lambda 256px — the self-interference golden's own regime
38
+ exitRecenter: true, // output coupler collapses the mouth to a point
39
+ exitPhaseReset: false // coherence OFF by default — turning it ON is the experiment
40
+ });
41
+ // 1. THE GAIN SOURCE — a hemisphere emitter just inside the input mouth, so the whole
42
+ // burst is aimed down the bore instead of half of it escaping backwards.
43
+ exp.createCanvas(W, H, SphereEmitter.worldCfg(spec.emitter)); // THE WORLD: a 2D canvas + universe — first, then parts
44
+ exp.addObject('SphereEmitter', spec.emitter);
45
+ // 2+3. THE BORE AND THE OUTPUT COUPLER — one directed Tunnel carrying the exit gate.
46
+ // mode 'directed': every wall hit re-emits forward within 180 degrees of the axis.
47
+ // exitRecenter / exitPhaseReset are the two coupler flags, both live in the Inspector.
48
+ exp.addObject('Tunnel', spec.tunnel);
49
+ }
@@ -0,0 +1,56 @@
1
+ /* Copyright 2023-2026 by Essam Abadir */
2
+
3
+ /**
4
+ * SCENE — 1A · Mirror (3D)
5
+ *
6
+ * A sketch file: the WHOLE scene as one ES module, `export default function buildExperiment(exp)`. The world
7
+ * (its co-init call, `exp.createCanvas` / `exp.createScene` — the one place its size is written),
8
+ * the parts (`exp.addObject`) and the render intent are all here; the sugar
9
+ * objects, renderer and engine are imports. Registered by lib/shim/registry/walkthrough.js
10
+ * (rung cl1a-mirror-3d).
11
+ */
12
+
13
+ import { SphereEmitter } from '@descix/frqtl-web/parts';
14
+
15
+ export default function buildExperiment(exp) {
16
+ // Collision Lab 1A · 3D — a collimated LASER (particle-walk pins PURE +x in 2D AND
17
+ // 3D) into a 3D mirror SLAB (depth → z-slab containing z=0), rendered as a box;
18
+ // orbit to view. Same LASER tuning as the 2D 1A: single positive
19
+ // charge, wavelength 1, wavelengthScale 1 (fundamentalWaveLength 4), tiny burst.
20
+ // FACE-ON default: orientation 0 presents the full
21
+ // drawn face to the beam → retro-reflection (beam straight back, recolored) — the
22
+ // one mirror visual that reads correctly from EVERY camera azimuth. (A tilted
23
+ // default's L-shaped 2th exit is correct optics but its mirror-flipped projection
24
+ // reads as pass-through from presets that view the xy-plane from behind — measured:
25
+ // zero leaves ever behind the face; the read was projection handedness, not physics.)
26
+ // Rotate the orientation slider to steer: 45 -> straight up, 30 -> R(120), etc.
27
+ var W = 600, H = 400; // THE WORLD this scene states (its co-init call below)
28
+ var cy = Math.round(H / 2);
29
+ var SRC = {
30
+ preset: 'particle-walk', is2D: false, center: [Math.round(W * 0.15), cy],
31
+ chargeMode: 'positive', fundamentalDimension: 2, wavelength: 1,
32
+ fundamentalWaveLength: 4, burstSize: 2, emitEveryTicks: 1
33
+ };
34
+ exp.createScene(W, H, 600, SphereEmitter.worldCfg(SRC)); // THE WORLD: a 3D scene + universe, 600x400x600 — first, then parts
35
+ exp.addObject('SphereEmitter', SRC);
36
+ exp.addObject('Wall', {
37
+ rect: [Math.round(W * 0.6), Math.round(H * 0.2), 20, Math.round(H * 0.6)],
38
+ z: -80, depth: 160,
39
+ collisionBehavior: 'bounce', bounceDirection: 'reflect', orientationDeg: 0,
40
+ name: 'mirror', color: [255, 120, 0], hooks: ['recolor']
41
+ });
42
+ // SCENE Z-COLLIMATOR (without it the z lets things pass through instead of
43
+ // reflecting): the beam's z-tail DIFFUSES over time (measured:
44
+ // |z| at the wall trending 68 of the 80 rim within seconds), and any quantum
45
+ // beyond the plate's z-band would sail BESIDE the plate — reading as pass-
46
+ // through from rooftop. Two INVISIBLE full-canvas destroy boundaries flush with
47
+ // the plate's z-band clamp the scene to the mirror's face: the universe z-edge
48
+ // moved inward (the sanctioned experiment-boundary sink, same as 2D strays
49
+ // dying at the canvas edge) — so the mirror provably faces EVERY alive quantum
50
+ // and nothing can ever appear past the plate. 40px deep: un-jumpable (max z
51
+ // step is ±2/tick).
52
+ exp.addObject('Wall', { rect: [0, 0, W, H], z: 80, depth: 40,
53
+ collisionBehavior: 'destroy', name: 'zClipFar', visible: false });
54
+ exp.addObject('Wall', { rect: [0, 0, W, H], z: -120, depth: 40,
55
+ collisionBehavior: 'destroy', name: 'zClipNear', visible: false });
56
+ }
@@ -0,0 +1,140 @@
1
+ /* Copyright 2023-2026 by Essam Abadir */
2
+
3
+ /**
4
+ * SCENE — 1D · Mirror Loop (10-mirror {10/3} star)
5
+ *
6
+ * A sketch file: the WHOLE scene as one ES module, `export default function buildExperiment(exp)`. The world
7
+ * (its co-init call, `exp.createCanvas` / `exp.createScene` — the one place its size is written),
8
+ * the parts (`exp.addObject`) and the render intent are all here; the sugar
9
+ * objects, renderer and engine are imports. Registered by lib/shim/registry/walkthrough.js
10
+ * (rung cl1d-mirror-route).
11
+ */
12
+
13
+ // A CLOSED {10/3} STAR BILLIARD: a 2-particle-wide laser loops
14
+ // m1→m2→…→m10→m1 FOREVER. Ten mirrors at the vertices of a regular decagon; each tilt solved
15
+ // from its in/out chords so the reflected centre-line hits the next mirror, and the star's
16
+ // symmetry closes the tenth leg back into the first. Each mirror tags the beam with its own
17
+ // colour (recolor hook) → the beam re-colours every bounce. No detector: the loop has no exit.
18
+ // The emitter's DECLARED emission gate (emissionCap/gateCounter — the blackbody pattern as
19
+ // captured descriptor DATA) keeps the population bounded so FPS stays healthy, Restart-safe.
20
+ //
21
+ // ONE MODE-AWARE SOURCE. The mode strip selects the RENDERER the host boots
22
+ // (renderState.renderer), and this scene reads it ONCE, before its world: `three` ⇒
23
+ // exp.createScene (a 600x400x600 world), else exp.createCanvas (600x400). The ring geometry,
24
+ // tilts, colours, laser and gate are the SAME in both modes (2D≡3D); `IS3D` guards exactly
25
+ // these deltas:
26
+ // (a) every mirror is a 3D SLAB — a z-slab centred on the beam plane z=0, rendered as a plate;
27
+ // (b) the laser is VOLUMETRIC (is2D:false — it braids in y AND z; the slab depth catches the
28
+ // z-braid; its tilted xy faces reflect by the 2θ law, its near/far z-faces bounce vz);
29
+ // (c) two invisible destroy z-collimators flush with the slab z-band;
30
+ // (d) the population counter carries a z-slab covering the WHOLE universe z-band;
31
+ // (e) MOVE/LOOK camera joysticks (the OMNI_3D pattern).
32
+ // The 3D mode's render intent — god-rays at the sun's settings, computed from the light
33
+ // particles only (godraySource 'leaf'), and the 'table-top' camera — rides the registry mode's
34
+ // renderState (lib/shim/registry/walkthrough.js), whose god-ray VALUES are the sun's, owned by
35
+ // lib/shim/render/sun-look.js.
36
+
37
+ import { CameraControls, SphereEmitter } from '@descix/frqtl-web/parts';
38
+ import * as FrqtlDisplay from '@descix/frqtl-web/compat/renderer/display-slot.js';
39
+
40
+ export default function buildExperiment(exp) {
41
+ // The booted display (the host's renderState.renderer) decides which world this mode makes.
42
+ var IS3D = FrqtlDisplay.name() === 'three';
43
+ var W = 600, H = 400, WORLD_D = 600; // THE WORLD this scene states (its co-init call below)
44
+ var f = Math.min(W, H) / 600;
45
+ // R 225·f: adjacent decagon vertices sit 2R·sin18° ≈ 0.618R apart vs slab
46
+ // height ~110·f, so the mirrors separate with clear gaps. Fit: R + rotated-slab half-diagonal
47
+ // (≈55·f) stays inside min(W,H)/2 with margin.
48
+ var CX = Math.round(W / 2), CY = Math.round(H / 2), R = Math.round(225 * f), HOP = 3, ROT = 12;
49
+ // CAP 6400 / burst 8 (brightness retune): a VERY BRIGHT braid. The cap is
50
+ // LIVE-controllable off the population counter (select 'population' in Layers → Inspector
51
+ // 'Population Gate').
52
+ var SW = Math.max(10, Math.round(14 * f)), SH = Math.max(70, Math.round(110 * f)), CAP = 6400;
53
+ // SD — the 3D slab z-depth: a 2:1 tile (twice the slab height, z-centred on the beam plane).
54
+ // The scene z-collimator clamps ALL quanta to this band, so every mirror provably faces every
55
+ // alive quantum.
56
+ var SD = 2 * SH;
57
+ // Each mirror a DIFFERENT colour = its identity (a red→magenta rainbow); the recolor hook
58
+ // stamps that colour onto every particle it reflects (string_map['render.color']).
59
+ var PAL = [[255,60,60],[255,140,0],[255,220,0],[150,230,40],[40,210,90],[0,210,190],[0,170,255],[70,90,255],[150,70,235],[235,50,190]];
60
+ // Hit-order vertices of the {10/3} star (m1..m10 named IN the order the beam visits them).
61
+ var order = []; for (var k = 0; k < 10; k++) { order.push((k * HOP) % 10); }
62
+ var D2R = Math.PI / 180;
63
+ var vpos = function (v) { var a = (v * 36 + ROT) * D2R; return [CX + R * Math.cos(a), CY + R * Math.sin(a)]; };
64
+ var pos = order.map(vpos);
65
+ var deg = function (a) { return ((a * 180 / Math.PI) % 360 + 360) % 360; };
66
+ var angOf = function (p, q) { return deg(Math.atan2(q[1] - p[1], q[0] - p[0])); };
67
+ // Per-mirror IN-PLANE orientation from the in/out chords: ori = (in+out−180)/2, branch chosen
68
+ // so the engine reflect law out = 180 + 2·ori − in reproduces the outgoing chord exactly.
69
+ // Orientation is z-axis rotation, so the 3D slab depth adds NO new angle.
70
+ var ORI = [];
71
+ for (var j = 0; j < 10; j++) {
72
+ var pr = pos[(j + 9) % 10], cu = pos[j], nx = pos[(j + 1) % 10];
73
+ var inA = angOf(pr, cu), outA = angOf(cu, nx);
74
+ var o = (((inA + outA - 180) / 2) % 360 + 360) % 360;
75
+ var op = ((180 + 2 * o - inA) % 360 + 360) % 360;
76
+ if (Math.abs(((op - outA + 540) % 360) - 180) > 0.5) { o = (o + 90) % 360; }
77
+ ORI.push(o);
78
+ }
79
+ // The NARROW STRAIGHT-WALK laser (the exemplar): the SAME emitter as Rung 1
80
+ // (Straight Walk) — preset 'particle-walk', every walk-character field INHERITED from the same
81
+ // factory defaults (chargeMode 'positive', dim 0 = 'light' P=1, fundamentalWaveLength 64 → the
82
+ // λ16 braided transverse ripple) — with ONLY the deliberate loop deltas: (a) a 2px source line
83
+ // (emissionBoxSide 2 vs r1's default 10), (b) seated on the m10→m1 leg JUST CLEAR of m10 (70·f
84
+ // past its vertex > the rotated-slab half-diagonal ≈55·f) and aimed along the leg (the longest
85
+ // clear throw: leg 1.618R ≈ 364·f), (c) a burst of 8/tick, and (d) the DECLARED emission gate.
86
+ var pS = pos[9], p0 = pos[0];
87
+ var dx = p0[0] - pS[0], dy = p0[1] - pS[1], L = Math.hypot(dx, dy), ux = dx / L, uy = dy / L;
88
+ var emit = [Math.round(pS[0] + 70 * f * ux), Math.round(pS[1] + 70 * f * uy)];
89
+ // EMISSION-CAP GATE as DECLARED DATA (the blackbody-thermostat pattern):
90
+ // emissionCap + gateCounter compile at CONSTRUCTION into a host tick-fn reading
91
+ // Wall.getLiveCount on the background counter named 'population' (placed below — the by-name
92
+ // reference resolves lazily on the first tick). The closed loop has NO sink, so the gate pauses
93
+ // emission at the cap and resumes below it: the population plateaus. Restart-safe: codegen
94
+ // captures the two fields and the rebuilt emitter recompiles the gate (no free recipe tick-fn).
95
+ // is2D:!IS3D opens activeAxes.z in 3D — the volumetric laser.
96
+ var SRC = {
97
+ preset: 'particle-walk', is2D: !IS3D, center: emit, orientationDeg: angOf(pS, p0),
98
+ emissionBoxSide: 2, burstSize: 8,
99
+ emissionCap: CAP, gateCounter: 'population'
100
+ };
101
+ // THE WORLD — first, then parts: a 3D scene + universe (600x400x600) or a 2D canvas + universe.
102
+ if (IS3D) { exp.createScene(W, H, WORLD_D, SphereEmitter.worldCfg(SRC)); }
103
+ else { exp.createCanvas(W, H, SphereEmitter.worldCfg(SRC)); }
104
+ exp.addObject('SphereEmitter', SRC);
105
+ // The ten mirrors at the star vertices — each its own colour + the recolor tag. In 3D each is a
106
+ // SLAB (z-slab −SD/2..SD/2); in 2D the bag is EMPTY, so the wall is the flat mirror.
107
+ var ZSLAB = IS3D ? { z: -Math.round(SD / 2), depth: SD } : {};
108
+ for (var i = 0; i < 10; i++) {
109
+ var p = pos[i];
110
+ exp.addObject('Wall', Object.assign(
111
+ { rect: [Math.round(p[0] - SW / 2), Math.round(p[1] - SH / 2), SW, SH] }, ZSLAB,
112
+ { collisionBehavior: 'bounce', bounceDirection: 'reflect', orientationDeg: ORI[i],
113
+ name: 'm' + (i + 1), color: PAL[i], hooks: ['recolor'] }));
114
+ }
115
+ if (IS3D) {
116
+ // SCENE Z-COLLIMATOR (without it the z lets things pass through instead of
117
+ // reflecting): the legs' z-braid diffuses lap over lap; any quantum beyond the mirrors'
118
+ // z-band would sail BESIDE a plate on the leg line — reading as a beam passing THROUGH the
119
+ // mirror. Two INVISIBLE full-canvas destroy boundaries flush with the slab z-band clamp the
120
+ // scene to the mirror faces (the universe z-edge moved inward — the sanctioned
121
+ // experiment-boundary sink). 40px deep: un-jumpable (max z step ±2/tick).
122
+ exp.addObject('Wall', { rect: [0, 0, W, H], z: Math.round(SD / 2), depth: 40,
123
+ collisionBehavior: 'destroy', name: 'zClipFar', visible: false });
124
+ exp.addObject('Wall', { rect: [0, 0, W, H], z: -Math.round(SD / 2) - 40, depth: 40,
125
+ collisionBehavior: 'destroy', name: 'zClipNear', visible: false });
126
+ }
127
+ // BACKGROUND POPULATION COUNTER (the canonical objects approach): an INVISIBLE
128
+ // full-canvas Wall with collisionBehavior 'nothing' + the count hook. Every live leaf inside its
129
+ // rect collides every tick, so its per-tick collided-frame count (Wall.getLiveCount, bench LO7
130
+ // mechanics) IS the live population — the ONE 'how many live' authority. In 3D it must contain
131
+ // EVERY live leaf: the universe z-band is ±half-width (z-strays DIE at it), so its z-slab is ±W
132
+ // (a strict superset). Counting never moves/kills/recolors a frame: zero physics (SU1).
133
+ exp.addObject('Wall', Object.assign(
134
+ { rect: [0, 0, W, H] }, IS3D ? { z: -W, depth: 2 * W } : {},
135
+ { collisionBehavior: 'nothing', hooks: ['count'], name: 'population', visible: false }));
136
+ // MOVE/LOOK camera joysticks — the OMNI_3D pattern (3D only).
137
+ if (IS3D && typeof document !== 'undefined' && exp.runner) {
138
+ if (exp.runner.controlHost) { CameraControls.attach(exp.runner, exp.runner.controlHost); }
139
+ }
140
+ }
@@ -0,0 +1,38 @@
1
+ /* Copyright 2023-2026 by Essam Abadir */
2
+
3
+ /**
4
+ * SCENE — 1A · Mirror
5
+ *
6
+ * A sketch file: the WHOLE scene as one ES module, `export default function buildExperiment(exp)`. The world
7
+ * (its co-init call, `exp.createCanvas` / `exp.createScene` — the one place its size is written),
8
+ * the parts (`exp.addObject`) and the render intent are all here; the sugar
9
+ * objects, renderer and engine are imports. Registered by lib/shim/registry/walkthrough.js
10
+ * (rung cl1a-mirror).
11
+ */
12
+
13
+ import { SphereEmitter } from '@descix/frqtl-web/parts';
14
+
15
+ export default function buildExperiment(exp) {
16
+ // Collision Lab 1A (Mirror) — a collimated LASER aimed at a rotatable Bounce/Reflect
17
+ // Wall. LASER TUNING: particle-walk pins PURE +x momentum (the
18
+ // tightest constrained-angle the emitter supports — zero angular spread); a SINGLE
19
+ // (positive) charge removes the random transverse braiding; wavelength 1 → the
20
+ // minimal transverse wiggle; fundamentalWaveLength 4 → wavelengthScale 1 (the
21
+ // 256px scale-spread REMOVED — that spray was the 'visually non-sensical' look);
22
+ // a TINY burst (2/tick) keeps it a thin beam (frame-rate protection). Rotate the
23
+ // mirror to steer the reflected beam: 45 -> straight-up exit, 30 -> R(120) exit.
24
+ var W = 600, H = 400; // THE WORLD this scene states (its co-init call below)
25
+ var cy = Math.round(H / 2);
26
+ var SRC = {
27
+ preset: 'particle-walk', is2D: true, center: [Math.round(W * 0.12), cy],
28
+ orientationDeg: 0, chargeMode: 'positive', fundamentalDimension: 2, wavelength: 1,
29
+ fundamentalWaveLength: 4, burstSize: 2, emitEveryTicks: 1
30
+ };
31
+ exp.createCanvas(W, H, SphereEmitter.worldCfg(SRC)); // THE WORLD: a 2D canvas + universe — first, then parts
32
+ exp.addObject('SphereEmitter', SRC);
33
+ exp.addObject('Wall', {
34
+ rect: [Math.round(W * 0.6), Math.round(H * 0.2), 20, Math.round(H * 0.6)],
35
+ collisionBehavior: 'bounce', bounceDirection: 'reflect',
36
+ orientationDeg: 45, name: 'mirror', color: [255, 120, 0], hooks: ['recolor']
37
+ });
38
+ }
@@ -0,0 +1,27 @@
1
+ /* Copyright 2023-2026 by Essam Abadir */
2
+
3
+ /**
4
+ * SCENE — 7 · 3D
5
+ *
6
+ * A sketch file: the WHOLE scene as one ES module, `export default function buildExperiment(exp)`. The world
7
+ * (its co-init call, `exp.createCanvas` / `exp.createScene` — the one place its size is written),
8
+ * the parts (`exp.addObject`) and the render intent are all here; the sugar
9
+ * objects, renderer and engine are imports. Registered by lib/shim/registry/walkthrough.js
10
+ * (rung r7-3d).
11
+ */
12
+
13
+ // The omni source released into 3D (is2D:false) + the reusable camera joysticks.
14
+
15
+ import { CameraControls, SphereEmitter } from '@descix/frqtl-web/parts';
16
+
17
+ export default function buildExperiment(exp) {
18
+ // is2D:false opens the z-axis: the ball-rejected sampler draws a 3D BALL of
19
+ // directions (bench S1). three renderer + perspective camera come from renderState.
20
+ // CameraControls.attach = reusable FAIL-SOFT joystick sugar (no-op in 2D).
21
+ var SRC = { preset: 'spherical', is2D: false };
22
+ exp.createScene(600, 400, 600, SphereEmitter.worldCfg(SRC)); // THE WORLD: a 3D scene + universe, 600x400x600 — first, then parts
23
+ exp.addObject('SphereEmitter', SRC);
24
+ if (typeof document !== 'undefined' && exp.runner) {
25
+ if (exp.runner.controlHost) { CameraControls.attach(exp.runner, exp.runner.controlHost); }
26
+ }
27
+ }
@@ -0,0 +1,22 @@
1
+ /* Copyright 2023-2026 by Essam Abadir */
2
+
3
+ /**
4
+ * SCENE — 3 · Omni Source
5
+ *
6
+ * A sketch file: the WHOLE scene as one ES module, `export default function buildExperiment(exp)`. The world
7
+ * (its co-init call, `exp.createCanvas` / `exp.createScene` — the one place its size is written),
8
+ * the parts (`exp.addObject`) and the render intent are all here; the sugar
9
+ * objects, renderer and engine are imports. Registered by lib/shim/registry/walkthrough.js
10
+ * (rung r3-omni-source).
11
+ */
12
+
13
+ import { SphereEmitter } from '@descix/frqtl-web/parts';
14
+
15
+ export default function buildExperiment(exp) {
16
+ // Rung 3 — full dispersion: the spherical preset draws (vx,vy) across the whole
17
+ // ball; in 2D the ball-rejected sampler collapses to an even DISK of directions
18
+ // (bench S5). One omni point source = the sun disk.
19
+ var SRC = { preset: 'spherical', is2D: true };
20
+ exp.createCanvas(600, 400, SphereEmitter.worldCfg(SRC)); // THE WORLD: a 2D canvas + universe — first, then parts
21
+ exp.addObject('SphereEmitter', SRC);
22
+ }
@@ -0,0 +1,39 @@
1
+ /* Copyright 2023-2026 by Essam Abadir */
2
+
3
+ /**
4
+ * SCENE — 4 · Self-Interference / 5 · Fountain Pool
5
+ *
6
+ * A sketch file: the WHOLE scene as one ES module, `export default function buildExperiment(exp)`. The world
7
+ * (its co-init call, `exp.createCanvas` / `exp.createScene` — the one place its size is written),
8
+ * the parts (`exp.addObject`) and the render intent are all here; the sugar
9
+ * objects, renderer and engine are imports. Registered by lib/shim/registry/walkthrough.js
10
+ * (rungs r4-self-interference, r5-fountain-pool).
11
+ */
12
+
13
+ // ── Shared physics recipe SOURCES (ONE authority per physics setup) ──────────
14
+ // The render-variant rungs REFERENCE these consts (never copy-paste) and express
15
+ // ONLY a renderState delta — so a future change to a base tuple flows to its
16
+ // variants automatically (no config mirror).
17
+ // The classic self-interference field (Rung 4). Reused VERBATIM by Rung 5
18
+ // (Fountain Pool) with only a water renderState delta.
19
+
20
+ import { SphereEmitter } from '@descix/frqtl-web/parts';
21
+
22
+ export default function buildExperiment(exp) {
23
+ // The classic self-interference tuple (matches self-interference-preset.png):
24
+ // dim 2 (capacity 16) + wavelength 32 -> clamped to 16 -> mass 1 (fullness 1/16);
25
+ // fundamentalWaveLength 64 -> wavelengthScale floor(64/4)=16 -> effective lambda 256px;
26
+ // chargeMode 'random' -> per-leaf +/- braiding (THE interference);
27
+ // emissionShell 'surface' + innerR 16 -> RING launch (empty center, sharp bands);
28
+ // burst 72/tick. Red is DERIVED from fullness 1/16 (ROYGBIV low end), not forced.
29
+ // Pattern = radial BRAIDED BANDS (not concentric rings).
30
+ var SRC = {
31
+ is2D: true, preset: 'spherical',
32
+ emissionShell: 'surface', innerR: 16,
33
+ fundamentalDimension: 2, wavelength: 32,
34
+ chargeMode: 'random', fundamentalWaveLength: 64,
35
+ burstSize: 72, emitEveryTicks: 1
36
+ };
37
+ exp.createCanvas(600, 400, SphereEmitter.worldCfg(SRC)); // THE WORLD: a 2D canvas + universe — first, then parts
38
+ exp.addObject('SphereEmitter', SRC);
39
+ }
@@ -0,0 +1,122 @@
1
+ /* Copyright 2023-2026 by Essam Abadir */
2
+
3
+ /**
4
+ * SCENE — Smoking Gun
5
+ *
6
+ * A sketch file: the WHOLE scene as one ES module, `export default function buildExperiment(exp)`. The 3D world, the
7
+ * muzzle, its wind-down, the bullet and its flight, and the painted gun body are all here; the
8
+ * sugar objects (SphereEmitter, Wall, LargeObject), the renderer and the engine are imports.
9
+ * Registered by lib/shim/registry/walkthrough.js (rung smoking-gun); the look and the camera ride
10
+ * that row's renderState.
11
+ *
12
+ * Composition (zero new physics): a 1×10 slit at the muzzle emits at-fundamental leaves with the
13
+ * particle-walk preset (+X momentum); brownian motion and inter-quantum collisions are on; the
14
+ * declared dimensions are 4, 8 and 12. The bullet is a Wall{bounce, reflect} cube that a tick-fn
15
+ * steps +1 px every second tick through Wall.setRect. A second tick-fn ramps the burst from 20 at
16
+ * tick 180 toward 0 at tick 600 and cuts the muzzle once when it rounds to 0.
17
+ *
18
+ * Order (it seeds the run): world → brownian/collision flags → the smoke ladder → the muzzle →
19
+ * the wind-down tick-fn → the bullet → its flight tick-fn → the gun body.
20
+ *
21
+ * Card text (this scene's what / why / how, verbatim; the scene is not on the
22
+ * showcase roster, lib/shim/registry/exhibits.js, so no front-page tile or GYM card shows it):
23
+ * What you are seeing:
24
+ * Explore how you can create CGI-like effects out of emergent physics - if you are a ThreeJS
25
+ * developer, this is your opportunity to shine! Presently, a gun fires, seen from the side. A
26
+ * slit at the muzzle, one pixel wide and ten tall, releases twenty quanta per tick heading down
27
+ * the barrel. The bullet is currently a ten-pixel reflecting cube (quanta bounce off it).
28
+ * Why it is impossible the usual way:
29
+ * Look into how you can use the collisions from the 3D Collisions Lab and the collision
30
+ * experiments to make the bullet self-propelled. You'll need an intuitive understanding of what
31
+ * the standard collisions in the model end up doing and possibly how Large Objects allow you to
32
+ * define your own custom hooks and collision behaviors. The goal is that the collisions of the
33
+ * smaller light quanta accumulate into bullet momentum instead of the currently scripted one
34
+ * pixel every second tick.
35
+ * How FRQTL gets it:
36
+ * Currently, the quanta jostle and collide with one another, and they promote into ever larger
37
+ * frames, from the fundamental layer through dimensions 4, 8 and 12. That climb is the smoke.
38
+ * After three seconds the muzzle winds down, and by ten seconds it is cut, leaving the plume to
39
+ * drift and spread on its own. No fluid dynamics, no gas law, no particle system scripted to
40
+ * look like smoke.
41
+ *
42
+ * Facts to help you out:
43
+ * - Muzzle: a 1×10 px slit, particle-walk preset (pure +X), 20 quanta per tick, at-fundamental leaves.
44
+ * - Brownian motion and inter-quantum collisions are on. Declared dimensions are 4, 8 and 12 (the
45
+ * scene's "smoke ladder": leaves promote 0 → 4 → 8 → 12).
46
+ * - The bullet's motion is scripted: a tick function steps it +1 px every second tick. The quanta
47
+ * do NOT push it.
48
+ * - Bullet: a 10 px cube Wall, collisionBehavior bounce/reflect, so quanta reflect off it.
49
+ * - Wind-down: full burst until tick 180, linear fall to zero at tick 600, then the muzzle is cut.
50
+ * The rate is capped at 60 ticks per second, so that is 3 s and 10 s.
51
+ * - The gun body is a painted shape with no collision, so it has no physical role.
52
+ * - Look: side profile (barrel reads left to right), glow 0.6, god rays 0.5 from the fundamental
53
+ * layer, heat 0.2, smoke render effect 0. The visible "smoke" is therefore the frames themselves,
54
+ * not a render effect.
55
+ */
56
+
57
+ import { CameraControls, CollisionTypes, LargeObject, SphereEmitter } from '@descix/frqtl-web/parts';
58
+
59
+ export default function buildExperiment(exp) {
60
+ var W = 600, H = 600, D = 600; // THE WORLD this scene states (its co-init call below)
61
+ var BURST = 20; // quanta per tick at the muzzle, before the wind-down
62
+ var BULLET_SIDE = 10; // the bullet cube's edge = the muzzle slit's height (px)
63
+ var RAMP_START = 180, RAMP_END = 600; // the wind-down: full burst until RAMP_START, zero at RAMP_END
64
+ var GUN_W = 150, GUN_H = 84; // the painted gun body (px); its right edge is the muzzle
65
+
66
+ var MUZZLE_X = Math.floor(W / 2), MUZZLE_Y = Math.floor(H / 2);
67
+ var SRC = {
68
+ preset: 'particle-walk', is2D: false, // pure +X momentum in 2D and 3D
69
+ center: [MUZZLE_X, MUZZLE_Y, 0],
70
+ emissionBox: { x: 0, y: BULLET_SIDE, z: 0 }, // the 1×10 slit
71
+ chargeMode: 'negative', burstSize: BURST, emitEveryTicks: 1,
72
+ fundamentalDimension: 0, fundamentalWaveLength: 64 // λ scale floor(64/4) = 16
73
+ };
74
+
75
+ // ── WORLD — a 3D scene + universe W×H×D, fundamental layer 0, λ multiplier 16 ──
76
+ exp.createScene(W, H, D, SphereEmitter.worldCfg(SRC));
77
+ var u = exp.universe;
78
+ u.brownianMotion = true;
79
+ u.withInterQuantumCollisions = true;
80
+ u.addDimension(4); // the smoke ladder: leaves promote 0 → 4 → 8 → 12
81
+ u.addDimension(8);
82
+ u.addDimension(12);
83
+ exp.runner.setRateLimits({ tpsLimit: 60 }); // pacing only: 60 ticks = 1 s of wall-clock
84
+
85
+ // ── THE MUZZLE ──
86
+ var muzzle = exp.addObject('SphereEmitter', SRC);
87
+
88
+ // ── THE WIND-DOWN — the burst falls linearly from BURST at RAMP_START to zero at RAMP_END ──
89
+ // The burst setter's floor is one quantum per tick, so zero is the muzzle's cut, issued once.
90
+ var rampTick = 0, muzzleCut = false;
91
+ exp.addTickFunction(function () {
92
+ rampTick++;
93
+ if (muzzleCut || rampTick < RAMP_START) { return; }
94
+ var n = Math.round(BURST * Math.max(0, 1 - (rampTick - RAMP_START) / (RAMP_END - RAMP_START)));
95
+ if (n >= 1) { muzzle.setBurstSize(n); } else { muzzle.setActive(false); muzzleCut = true; }
96
+ });
97
+
98
+ // ── THE BULLET — a reflecting wall cube at the muzzle, stepped +1 px every second tick ──
99
+ var bulletLeft = MUZZLE_X, bulletTop = MUZZLE_Y - BULLET_SIDE / 2;
100
+ var bullet = exp.addObject('Wall', {
101
+ rect: [bulletLeft, bulletTop, -BULLET_SIDE / 2, BULLET_SIDE, BULLET_SIDE, BULLET_SIDE],
102
+ collisionBehavior: 'bounce', bounceDirection: 'reflect', shellShape: 'box',
103
+ color: [235, 205, 150], name: 'bullet'
104
+ });
105
+ var flightTick = 0;
106
+ exp.addTickFunction(function () {
107
+ flightTick++;
108
+ if (flightTick % 2 !== 0 || bulletLeft + BULLET_SIDE >= W) { return; } // stops at the far wall
109
+ bulletLeft += 1;
110
+ bullet.setRect([bulletLeft, bulletTop, BULLET_SIDE, BULLET_SIDE]); // planar: z and depth kept
111
+ });
112
+
113
+ // ── THE GUN BODY — a painted occluder (no collision); the renderer paints the 'gun' hint ──
114
+ var gun = new LargeObject(u, [MUZZLE_X - GUN_W + 12, MUZZLE_Y - GUN_H / 2, GUN_W, GUN_H],
115
+ CollisionTypes.NONE, [], 'gun', 'closest', null, 1, [46, 46, 52]);
116
+ gun.renderHint = 'gun';
117
+
118
+ // ── MOVE/LOOK pads ──
119
+ if (typeof document !== 'undefined' && exp.runner.controlHost) {
120
+ CameraControls.attach(exp.runner, exp.runner.controlHost);
121
+ }
122
+ }
@@ -0,0 +1,22 @@
1
+ /* Copyright 2023-2026 by Essam Abadir */
2
+
3
+ /**
4
+ * SCENE — 1 · Straight Walk
5
+ *
6
+ * A sketch file: the WHOLE scene as one ES module, `export default function buildExperiment(exp)`. The world
7
+ * (its co-init call, `exp.createCanvas` / `exp.createScene` — the one place its size is written),
8
+ * the parts (`exp.addObject`) and the render intent are all here; the sugar
9
+ * objects, renderer and engine are imports. Registered by lib/shim/registry/walkthrough.js
10
+ * (rung r1-straight-walk).
11
+ */
12
+
13
+ import { SphereEmitter } from '@descix/frqtl-web/parts';
14
+
15
+ export default function buildExperiment(exp) {
16
+ // Rung 1 — deterministic +X drift (particle-walk preset pins vx=[R,R], vy=vz=0)
17
+ // with the tiny always-armed transverse coin. Born AT the fundamental (dim 0)
18
+ // so it is 'light' — steps every tick (fast straight drift).
19
+ var SRC = { preset: 'particle-walk', is2D: true };
20
+ exp.createCanvas(600, 400, SphereEmitter.worldCfg(SRC)); // THE WORLD: a 2D canvas + universe — first, then parts
21
+ exp.addObject('SphereEmitter', SRC);
22
+ }
@@ -0,0 +1,39 @@
1
+ /* Copyright 2023-2026 by Essam Abadir */
2
+
3
+ /**
4
+ * SCENE — 8 · Sun
5
+ *
6
+ * A sketch file: the WHOLE scene as one ES module, `export default function buildExperiment(exp)`. The world
7
+ * (its co-init call, `exp.createCanvas` / `exp.createScene` — the one place its size is written),
8
+ * the parts (`exp.addObject`) and the render intent are all here; the sugar
9
+ * objects, renderer and engine are imports. Registered by lib/shim/registry/walkthrough.js
10
+ * (rung r8-sun).
11
+ */
12
+
13
+ // The sun — the 3D omni POINT source at the sun.png panel-visible regime
14
+ // (supersedes the bare r-code-a-sun reuse for THIS rung). Panel knobs:
15
+ // dim 2, virtual mass 16 (mass/cap 16/16, fullness 1 — the density driver, ~25012
16
+ // activeQuanta) via wavelength arg 1 (mass = max(1, capacity 16 / 1) = 16, verified
17
+ // vs the factory clamp); λ scale (wavelengthScale) 16 via fundamentalWaveLength 64
18
+ // (waveLengthMultiplier = max(1, floor(64/4)) = 16 → eff λ (16/16)×16 = 16px); emit
19
+ // every 1. force-red OFF (no color), water OFF, source-mesh OFF. FX ride the renderState
20
+ // (values: lib/shim/render/sun-look.js).
21
+
22
+ import { CameraControls, SphereEmitter } from '@descix/frqtl-web/parts';
23
+
24
+ export default function buildExperiment(exp) {
25
+ // Rung 8 (Sun) — the sun.png panel regime: a 3D omni POINT source, virtual mass 16
26
+ // (fullness 1) via wavelength:1, λ scale 16 via fundamentalWaveLength:64, emit every 1.
27
+ // The sphere shape + god-rays + glow FX ride the renderState (three-only capabilities).
28
+ // The sun's yellow is the NATURAL fullness->color (mass=capacity, fullness 1); no forced color.
29
+ var SRC = {
30
+ preset: 'spherical', emissionBoxSide: 0, is2D: false,
31
+ chargeMode: 'random', fundamentalDimension: 2,
32
+ wavelength: 1, fundamentalWaveLength: 64, emitEveryTicks: 1
33
+ };
34
+ exp.createScene(600, 400, 600, SphereEmitter.worldCfg(SRC)); // THE WORLD: a 3D scene + universe, 600x400x600 — first, then parts
35
+ exp.addObject('SphereEmitter', SRC);
36
+ if (typeof document !== 'undefined' && exp.runner) {
37
+ if (exp.runner.controlHost) { CameraControls.attach(exp.runner, exp.runner.controlHost); }
38
+ }
39
+ }
@@ -0,0 +1,37 @@
1
+ /* Copyright 2023-2026 by Essam Abadir */
2
+
3
+ /**
4
+ * SCENE — 6A · Two Sources / 6B · Two Fountains / 6C · Plasma Fusion
5
+ *
6
+ * A sketch file: the WHOLE scene as one ES module, `export default function buildExperiment(exp)`. The world
7
+ * (its co-init call, `exp.createCanvas` / `exp.createScene` — the one place its size is written),
8
+ * the parts (`exp.addObject`) and the render intent are all here; the sugar
9
+ * objects, renderer and engine are imports. Registered by lib/shim/registry/walkthrough.js
10
+ * (rungs r6a-two-source, r6b-two-fountains, r6c-plasma-fusion).
11
+ */
12
+
13
+ // Two self-interference sources ±32px apart (the classic config called TWICE — one
14
+ // world, two parts). Reused VERBATIM by Rung 6B (Two Fountains) + 6C (Plasma Fusion)
15
+ // — render deltas only.
16
+
17
+ import { SphereEmitter } from '@descix/frqtl-web/parts';
18
+
19
+ export default function buildExperiment(exp) {
20
+ // The classic self-interference config called TWICE, centered ±32px from canvas
21
+ // center (64px apart = 1×fundamentalWaveLength, i.e. λ_eff/4 since λ_eff = 4×fWL).
22
+ // The world is init'd ONCE, then TWO parts are constructed on it — no flag, no
23
+ // re-init, no stacking. The
24
+ // lattice BETWEEN the two visible sources is EMERGENT density superposition (SU1).
25
+ var W = 600, H = 400; // THE WORLD this scene states (its co-init call below)
26
+ var cx = Math.floor(W / 2), cy = Math.floor(H / 2);
27
+ var CFG = {
28
+ is2D: true, preset: 'spherical',
29
+ emissionShell: 'surface', innerR: 16,
30
+ fundamentalDimension: 2, wavelength: 32,
31
+ chargeMode: 'random', fundamentalWaveLength: 64,
32
+ burstSize: 72, emitEveryTicks: 1
33
+ };
34
+ exp.createCanvas(W, H, SphereEmitter.worldCfg(CFG)); // THE WORLD: a 2D canvas + universe — first, then parts
35
+ exp.addObject('SphereEmitter', Object.assign({}, CFG, { center: [cx - 32, cy] }));
36
+ exp.addObject('SphereEmitter', Object.assign({}, CFG, { center: [cx + 32, cy] }));
37
+ }
@@ -0,0 +1,26 @@
1
+ /* Copyright 2023-2026 by Essam Abadir */
2
+
3
+ /**
4
+ * SCENE — 2 · Wave
5
+ *
6
+ * A sketch file: the WHOLE scene as one ES module, `export default function buildExperiment(exp)`. The world
7
+ * (its co-init call, `exp.createCanvas` / `exp.createScene` — the one place its size is written),
8
+ * the parts (`exp.addObject`) and the render intent are all here; the sugar
9
+ * objects, renderer and engine are imports. Registered by lib/shim/registry/walkthrough.js
10
+ * (rung r2-wave).
11
+ */
12
+
13
+ import { SphereEmitter } from '@descix/frqtl-web/parts';
14
+
15
+ export default function buildExperiment(exp) {
16
+ // Rung 2 — Rung 1 + raise the leaf dimension to 2 (WAVELENGTH_DEMO_DIMENSION):
17
+ // wavelength is a NO-OP at dim 0 (capacity=1 saturates mass), so raising the
18
+ // fundamental gives the wavelength arg leverage. wavelength:8 -> mass 2 ->
19
+ // transverse period grows from ~16px (Rung 1) to a visible ~128px snake.
20
+ var SRC = {
21
+ preset: 'particle-walk', is2D: true,
22
+ fundamentalDimension: 2, wavelength: 8
23
+ };
24
+ exp.createCanvas(600, 400, SphereEmitter.worldCfg(SRC)); // THE WORLD: a 2D canvas + universe — first, then parts
25
+ exp.addObject('SphereEmitter', SRC);
26
+ }