@the-inclusionist/engine 9.0.0 → 11.0.0

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 (532) hide show
  1. package/README.md +120 -78
  2. package/app/css/style.css +761 -377
  3. package/app/public/vendor/fonts/playwrite-cu.woff2 +0 -0
  4. package/app/public/vendor/fonts/playwrite-es-deco.woff2 +0 -0
  5. package/app/public/vendor/fonts/playwrite-es.woff2 +0 -0
  6. package/app/public/vendor/fonts/playwrite-gb-j.woff2 +0 -0
  7. package/app/public/vendor/fonts/playwrite-gb-s.woff2 +0 -0
  8. package/app/public/vendor/fonts/playwrite-pe.woff2 +0 -0
  9. package/app/public/vendor/fonts/playwrite-pt.woff2 +0 -0
  10. package/app/public/vendor/fonts-licences/NOTICE.txt +166 -0
  11. package/app/public/vendor/fonts-licences/OFL-1.1.txt +86 -0
  12. package/app/public/vendor/fonts.css +36 -84
  13. package/dist-pkg/boot/create-game.d.ts +499 -219
  14. package/dist-pkg/boot/create-game.js +3944 -562
  15. package/dist-pkg/core/a11y-sr.d.ts +25 -3
  16. package/dist-pkg/core/a11y-sr.js +38 -19
  17. package/dist-pkg/core/accessible-label.d.ts +17 -0
  18. package/dist-pkg/core/accessible-label.js +37 -0
  19. package/dist-pkg/core/accommodation-subjects.d.ts +26 -0
  20. package/dist-pkg/core/accommodation-subjects.js +32 -0
  21. package/dist-pkg/core/accommodations.d.ts +125 -0
  22. package/dist-pkg/core/accommodations.js +195 -0
  23. package/dist-pkg/core/actions.d.ts +108 -55
  24. package/dist-pkg/core/actions.js +122 -71
  25. package/dist-pkg/core/calm-mode.d.ts +31 -0
  26. package/dist-pkg/core/calm-mode.js +47 -0
  27. package/dist-pkg/core/camera-cycle.d.ts +15 -0
  28. package/dist-pkg/core/camera-cycle.js +7 -0
  29. package/dist-pkg/core/caption-duration.d.ts +15 -0
  30. package/dist-pkg/core/caption-duration.js +19 -0
  31. package/dist-pkg/core/cartridge-problems.d.ts +34 -0
  32. package/dist-pkg/core/cartridge-problems.js +53 -0
  33. package/dist-pkg/core/constants.d.ts +0 -54
  34. package/dist-pkg/core/constants.js +9 -76
  35. package/dist-pkg/core/contract.d.ts +142 -164
  36. package/dist-pkg/core/contract.js +222 -208
  37. package/dist-pkg/core/dom-query.d.ts +4 -4
  38. package/dist-pkg/core/dom-query.js +12 -20
  39. package/dist-pkg/core/entity.d.ts +62 -77
  40. package/dist-pkg/core/entity.js +18 -32
  41. package/dist-pkg/core/escape-html.d.ts +9 -10
  42. package/dist-pkg/core/escape-html.js +16 -20
  43. package/dist-pkg/core/flash-threshold.d.ts +17 -0
  44. package/dist-pkg/core/flash-threshold.js +113 -0
  45. package/dist-pkg/core/game-speed.d.ts +11 -0
  46. package/dist-pkg/core/game-speed.js +16 -0
  47. package/dist-pkg/core/genres.d.ts +20 -0
  48. package/dist-pkg/core/genres.js +44 -0
  49. package/dist-pkg/core/i18n.d.ts +71 -60
  50. package/dist-pkg/core/i18n.js +186 -200
  51. package/dist-pkg/core/loop.d.ts +17 -6
  52. package/dist-pkg/core/loop.js +26 -26
  53. package/dist-pkg/core/pause-icon-catalogue.d.ts +15 -0
  54. package/dist-pkg/core/pause-icon-catalogue.js +54 -0
  55. package/dist-pkg/core/ring.d.ts +17 -0
  56. package/dist-pkg/core/ring.js +29 -0
  57. package/dist-pkg/core/rng.d.ts +7 -12
  58. package/dist-pkg/core/rng.js +23 -53
  59. package/dist-pkg/core/route.d.ts +26 -26
  60. package/dist-pkg/core/route.js +126 -121
  61. package/dist-pkg/core/scenes.d.ts +37 -40
  62. package/dist-pkg/core/scenes.js +41 -43
  63. package/dist-pkg/core/screens.d.ts +4 -4
  64. package/dist-pkg/core/screens.js +11 -16
  65. package/dist-pkg/core/session-clock.d.ts +23 -0
  66. package/dist-pkg/core/session-clock.js +37 -0
  67. package/dist-pkg/core/setting-defaults.d.ts +61 -0
  68. package/dist-pkg/core/setting-defaults.js +66 -0
  69. package/dist-pkg/core/speech-rate.d.ts +29 -0
  70. package/dist-pkg/core/speech-rate.js +47 -0
  71. package/dist-pkg/core/state.d.ts +118 -118
  72. package/dist-pkg/core/state.js +322 -297
  73. package/dist-pkg/core/visual-cycles.d.ts +30 -0
  74. package/dist-pkg/core/visual-cycles.js +52 -0
  75. package/dist-pkg/core/visual-state.d.ts +13 -0
  76. package/dist-pkg/core/visual-state.js +6 -0
  77. package/dist-pkg/educational/activities-registry.d.ts +1 -1
  78. package/dist-pkg/educational/activities-registry.js +9 -8
  79. package/dist-pkg/educational/adaptive-engine.d.ts +11 -11
  80. package/dist-pkg/educational/adaptive-engine.js +17 -17
  81. package/dist-pkg/educational/segment-bar.d.ts +12 -12
  82. package/dist-pkg/educational/segment-bar.js +9 -9
  83. package/dist-pkg/i18n/en.js +324 -223
  84. package/dist-pkg/i18n/es.js +323 -223
  85. package/dist-pkg/i18n/pt.js +348 -226
  86. package/dist-pkg/input/default-bindings.d.ts +37 -38
  87. package/dist-pkg/input/default-bindings.js +127 -144
  88. package/dist-pkg/input/devices.d.ts +7 -7
  89. package/dist-pkg/input/devices.js +17 -16
  90. package/dist-pkg/input/edges.d.ts +23 -32
  91. package/dist-pkg/input/edges.js +23 -28
  92. package/dist-pkg/input/empathy-filter.d.ts +22 -0
  93. package/dist-pkg/input/empathy-filter.js +34 -0
  94. package/dist-pkg/input/face-map.d.ts +96 -0
  95. package/dist-pkg/input/face-map.js +255 -0
  96. package/dist-pkg/input/face-signals.d.ts +40 -0
  97. package/dist-pkg/input/face-signals.js +48 -0
  98. package/dist-pkg/input/gamepad.d.ts +195 -145
  99. package/dist-pkg/input/gamepad.js +383 -556
  100. package/dist-pkg/input/gaze-cycle.d.ts +64 -0
  101. package/dist-pkg/input/gaze-cycle.js +133 -0
  102. package/dist-pkg/input/gaze-relative.d.ts +68 -0
  103. package/dist-pkg/input/gaze-relative.js +142 -0
  104. package/dist-pkg/input/hand-map.d.ts +28 -0
  105. package/dist-pkg/input/hand-map.js +142 -0
  106. package/dist-pkg/input/input-cooldown.d.ts +17 -0
  107. package/dist-pkg/input/input-cooldown.js +39 -0
  108. package/dist-pkg/input/key-default.d.ts +30 -0
  109. package/dist-pkg/input/key-default.js +60 -0
  110. package/dist-pkg/input/keyboard-runtime.d.ts +15 -21
  111. package/dist-pkg/input/keyboard-runtime.js +23 -27
  112. package/dist-pkg/input/keyboard.d.ts +68 -63
  113. package/dist-pkg/input/keyboard.js +83 -105
  114. package/dist-pkg/input/keydown.d.ts +123 -137
  115. package/dist-pkg/input/keydown.js +284 -289
  116. package/dist-pkg/input/latch-edge.d.ts +33 -21
  117. package/dist-pkg/input/latch-edge.js +34 -35
  118. package/dist-pkg/input/latch-scope.d.ts +51 -50
  119. package/dist-pkg/input/latch-scope.js +61 -82
  120. package/dist-pkg/input/latch-store.d.ts +26 -30
  121. package/dist-pkg/input/latch-store.js +42 -50
  122. package/dist-pkg/input/latch-sync.d.ts +29 -29
  123. package/dist-pkg/input/latch-sync.js +25 -25
  124. package/dist-pkg/input/latch.d.ts +14 -17
  125. package/dist-pkg/input/latch.js +29 -37
  126. package/dist-pkg/input/pad-defaults.d.ts +13 -16
  127. package/dist-pkg/input/pad-defaults.js +21 -28
  128. package/dist-pkg/input/pad-reading.d.ts +76 -0
  129. package/dist-pkg/input/pad-reading.js +169 -0
  130. package/dist-pkg/input/pad-wizard.d.ts +99 -0
  131. package/dist-pkg/input/pad-wizard.js +256 -0
  132. package/dist-pkg/input/pointer-space.d.ts +19 -20
  133. package/dist-pkg/input/pointer-space.js +27 -32
  134. package/dist-pkg/input/pointer.d.ts +39 -40
  135. package/dist-pkg/input/pointer.js +42 -45
  136. package/dist-pkg/input/state.d.ts +101 -89
  137. package/dist-pkg/input/state.js +54 -134
  138. package/dist-pkg/input/switch-scan.d.ts +59 -0
  139. package/dist-pkg/input/switch-scan.js +67 -0
  140. package/dist-pkg/input/synthetic-source.d.ts +42 -0
  141. package/dist-pkg/input/synthetic-source.js +57 -0
  142. package/dist-pkg/input/touch-bindings.d.ts +127 -116
  143. package/dist-pkg/input/touch-bindings.js +158 -173
  144. package/dist-pkg/input/touch.d.ts +147 -72
  145. package/dist-pkg/input/touch.js +362 -126
  146. package/dist-pkg/input/transport-in-use.d.ts +107 -0
  147. package/dist-pkg/input/transport-in-use.js +130 -0
  148. package/dist-pkg/input/transports.d.ts +90 -117
  149. package/dist-pkg/input/transports.js +104 -106
  150. package/dist-pkg/input/virtual-controller.d.ts +82 -0
  151. package/dist-pkg/input/virtual-controller.js +69 -0
  152. package/dist-pkg/input/vocabulary-migration.d.ts +50 -49
  153. package/dist-pkg/input/vocabulary-migration.js +80 -79
  154. package/dist-pkg/input/voice-map.d.ts +59 -0
  155. package/dist-pkg/input/voice-map.js +123 -0
  156. package/dist-pkg/platform/audio-ambient.d.ts +13 -2
  157. package/dist-pkg/platform/audio-ambient.js +14 -14
  158. package/dist-pkg/platform/audio-earcons.d.ts +20 -19
  159. package/dist-pkg/platform/audio-earcons.js +51 -42
  160. package/dist-pkg/platform/audio-jingles.js +9 -10
  161. package/dist-pkg/platform/audio-mixer.d.ts +14 -2
  162. package/dist-pkg/platform/audio-mixer.js +31 -39
  163. package/dist-pkg/platform/audio-sonar.d.ts +49 -152
  164. package/dist-pkg/platform/audio-sonar.js +124 -302
  165. package/dist-pkg/platform/audio.d.ts +62 -19
  166. package/dist-pkg/platform/audio.js +193 -168
  167. package/dist-pkg/platform/choose-by-voice.d.ts +70 -0
  168. package/dist-pkg/platform/choose-by-voice.js +157 -0
  169. package/dist-pkg/platform/flash-sampler.d.ts +19 -0
  170. package/dist-pkg/platform/flash-sampler.js +79 -0
  171. package/dist-pkg/platform/font-library.d.ts +77 -0
  172. package/dist-pkg/platform/font-library.js +98 -0
  173. package/dist-pkg/platform/font-library.json +721 -0
  174. package/dist-pkg/platform/heavy-catalogue.d.ts +77 -0
  175. package/dist-pkg/platform/heavy-catalogue.js +256 -0
  176. package/dist-pkg/platform/heavy-mirror.d.ts +20 -0
  177. package/dist-pkg/platform/heavy-mirror.js +73 -0
  178. package/dist-pkg/platform/heavy.d.ts +136 -0
  179. package/dist-pkg/platform/heavy.js +324 -0
  180. package/dist-pkg/platform/interruptible-speech.d.ts +23 -16
  181. package/dist-pkg/platform/interruptible-speech.js +77 -54
  182. package/dist-pkg/platform/kokoro-port.d.ts +27 -0
  183. package/dist-pkg/platform/kokoro-port.js +50 -0
  184. package/dist-pkg/platform/kokoro-runtime.d.ts +20 -0
  185. package/dist-pkg/platform/kokoro-runtime.js +52 -0
  186. package/dist-pkg/platform/kokoro.d.ts +70 -0
  187. package/dist-pkg/platform/kokoro.js +133 -0
  188. package/dist-pkg/platform/listener-scope.d.ts +12 -0
  189. package/dist-pkg/platform/listener-scope.js +90 -0
  190. package/dist-pkg/platform/locale-host.d.ts +14 -0
  191. package/dist-pkg/platform/locale-host.js +45 -0
  192. package/dist-pkg/platform/microphone.d.ts +51 -0
  193. package/dist-pkg/platform/microphone.js +118 -0
  194. package/dist-pkg/platform/onnx-runtime.d.ts +34 -0
  195. package/dist-pkg/platform/onnx-runtime.js +42 -0
  196. package/dist-pkg/platform/reading-in-worker.d.ts +64 -0
  197. package/dist-pkg/platform/reading-in-worker.js +125 -0
  198. package/dist-pkg/platform/reading-model.d.ts +94 -0
  199. package/dist-pkg/platform/reading-model.js +272 -0
  200. package/dist-pkg/platform/reading-runtime.d.ts +24 -0
  201. package/dist-pkg/platform/reading-runtime.js +164 -0
  202. package/dist-pkg/platform/reading-worker.d.ts +41 -0
  203. package/dist-pkg/platform/reading-worker.js +58 -0
  204. package/dist-pkg/platform/reading.d.ts +80 -0
  205. package/dist-pkg/platform/reading.js +136 -0
  206. package/dist-pkg/platform/speech-recognition.d.ts +60 -0
  207. package/dist-pkg/platform/speech-recognition.js +104 -0
  208. package/dist-pkg/platform/speech.d.ts +23 -1
  209. package/dist-pkg/platform/speech.js +29 -18
  210. package/dist-pkg/platform/storage-keys.d.ts +96 -0
  211. package/dist-pkg/platform/storage-keys.js +106 -0
  212. package/dist-pkg/platform/storage.d.ts +46 -111
  213. package/dist-pkg/platform/storage.js +104 -169
  214. package/dist-pkg/platform/tts.d.ts +85 -39
  215. package/dist-pkg/platform/tts.js +447 -127
  216. package/dist-pkg/platform/vision-loop.d.ts +23 -0
  217. package/dist-pkg/platform/vision-loop.js +56 -0
  218. package/dist-pkg/platform/vision.d.ts +132 -0
  219. package/dist-pkg/platform/vision.js +117 -0
  220. package/dist-pkg/platform/voice-listener.d.ts +40 -0
  221. package/dist-pkg/platform/voice-listener.js +88 -0
  222. package/dist-pkg/platform/voice-plan.d.ts +15 -98
  223. package/dist-pkg/platform/voice-plan.js +56 -143
  224. package/dist-pkg/platform/vosk-runtime.d.ts +96 -0
  225. package/dist-pkg/platform/vosk-runtime.js +151 -0
  226. package/dist-pkg/platform/vosk-vocabulary.d.ts +6 -0
  227. package/dist-pkg/platform/vosk-vocabulary.js +178 -0
  228. package/dist-pkg/render/canvas.d.ts +13 -7
  229. package/dist-pkg/render/canvas.js +13 -13
  230. package/dist-pkg/render/crt.d.ts +48 -12
  231. package/dist-pkg/render/crt.js +78 -80
  232. package/dist-pkg/render/cvd-matrices.d.ts +22 -18
  233. package/dist-pkg/render/cvd-matrices.js +37 -38
  234. package/dist-pkg/render/hc-role-data.d.ts +7 -7
  235. package/dist-pkg/render/hc-role-data.js +14 -14
  236. package/dist-pkg/render/high-contrast.d.ts +67 -56
  237. package/dist-pkg/render/high-contrast.js +226 -217
  238. package/dist-pkg/render/low-vision-drawing.d.ts +5 -0
  239. package/dist-pkg/render/low-vision-drawing.js +46 -0
  240. package/dist-pkg/render/lq-filter.d.ts +32 -20
  241. package/dist-pkg/render/lq-filter.js +59 -65
  242. package/dist-pkg/render/port.d.ts +86 -88
  243. package/dist-pkg/render/port.js +17 -23
  244. package/dist-pkg/render/screen-pipeline.d.ts +42 -42
  245. package/dist-pkg/render/screen-pipeline.js +80 -87
  246. package/dist-pkg/render/sprite-fx.d.ts +2 -1
  247. package/dist-pkg/render/sprite-fx.js +16 -14
  248. package/dist-pkg/render/viewports.d.ts +20 -15
  249. package/dist-pkg/render/viewports.js +83 -114
  250. package/dist-pkg/render/viz-axes-labels.d.ts +47 -0
  251. package/dist-pkg/render/viz-axes-labels.js +88 -0
  252. package/dist-pkg/render/viz-axes.d.ts +89 -86
  253. package/dist-pkg/render/viz-axes.js +128 -116
  254. package/dist-pkg/render/viz-modes.d.ts +28 -29
  255. package/dist-pkg/render/viz-modes.js +40 -45
  256. package/dist-pkg/render/viz-refusal.d.ts +32 -0
  257. package/dist-pkg/render/viz-refusal.js +57 -0
  258. package/dist-pkg/render/viz-setters.d.ts +104 -66
  259. package/dist-pkg/render/viz-setters.js +182 -191
  260. package/dist-pkg/ui/aac-sets.d.ts +45 -0
  261. package/dist-pkg/ui/aac-sets.js +41 -0
  262. package/dist-pkg/ui/audio-choices.d.ts +68 -0
  263. package/dist-pkg/ui/audio-choices.js +98 -0
  264. package/dist-pkg/ui/audio-rows-that-apply.d.ts +12 -0
  265. package/dist-pkg/ui/audio-rows-that-apply.js +43 -0
  266. package/dist-pkg/ui/camera-control.d.ts +53 -0
  267. package/dist-pkg/ui/camera-control.js +48 -0
  268. package/dist-pkg/ui/changed-mark.d.ts +9 -8
  269. package/dist-pkg/ui/changed-mark.js +22 -53
  270. package/dist-pkg/ui/control-choices.d.ts +37 -0
  271. package/dist-pkg/ui/control-choices.js +84 -0
  272. package/dist-pkg/ui/debug-panel.d.ts +59 -43
  273. package/dist-pkg/ui/debug-panel.js +68 -69
  274. package/dist-pkg/ui/declared-words.d.ts +21 -0
  275. package/dist-pkg/ui/declared-words.js +66 -0
  276. package/dist-pkg/ui/dom.d.ts +10 -14
  277. package/dist-pkg/ui/dom.js +10 -47
  278. package/dist-pkg/ui/drawing-problems.d.ts +25 -0
  279. package/dist-pkg/ui/drawing-problems.js +94 -0
  280. package/dist-pkg/ui/eye-control.d.ts +36 -0
  281. package/dist-pkg/ui/eye-control.js +178 -0
  282. package/dist-pkg/ui/face-control.d.ts +25 -0
  283. package/dist-pkg/ui/face-control.js +183 -0
  284. package/dist-pkg/ui/focus-trap.d.ts +39 -49
  285. package/dist-pkg/ui/focus-trap.js +56 -65
  286. package/dist-pkg/ui/fonts.d.ts +157 -68
  287. package/dist-pkg/ui/fonts.js +305 -115
  288. package/dist-pkg/ui/footer-scroll-driver.d.ts +14 -0
  289. package/dist-pkg/ui/footer-scroll-driver.js +201 -0
  290. package/dist-pkg/ui/footer-scroll.d.ts +38 -0
  291. package/dist-pkg/ui/footer-scroll.js +55 -0
  292. package/dist-pkg/ui/game-options.d.ts +47 -0
  293. package/dist-pkg/ui/game-options.js +158 -0
  294. package/dist-pkg/ui/gaze-overlay.d.ts +64 -0
  295. package/dist-pkg/ui/gaze-overlay.js +165 -0
  296. package/dist-pkg/ui/hand-control.d.ts +25 -0
  297. package/dist-pkg/ui/hand-control.js +143 -0
  298. package/dist-pkg/ui/help-panel.d.ts +87 -0
  299. package/dist-pkg/ui/help-panel.js +242 -0
  300. package/dist-pkg/ui/hud-bands.d.ts +62 -0
  301. package/dist-pkg/ui/hud-bands.js +146 -0
  302. package/dist-pkg/ui/hud-row.d.ts +34 -0
  303. package/dist-pkg/ui/hud-row.js +80 -0
  304. package/dist-pkg/ui/hud.d.ts +73 -73
  305. package/dist-pkg/ui/hud.js +94 -98
  306. package/dist-pkg/ui/item-announcement.d.ts +13 -12
  307. package/dist-pkg/ui/item-announcement.js +25 -26
  308. package/dist-pkg/ui/layout.d.ts +103 -28
  309. package/dist-pkg/ui/layout.js +117 -99
  310. package/dist-pkg/ui/libras-avatar-clip.d.ts +30 -0
  311. package/dist-pkg/ui/libras-avatar-clip.js +86 -0
  312. package/dist-pkg/ui/libras-avatar-load.d.ts +52 -0
  313. package/dist-pkg/ui/libras-avatar-load.js +134 -0
  314. package/dist-pkg/ui/libras-avatar-plan.d.ts +102 -0
  315. package/dist-pkg/ui/libras-avatar-plan.js +211 -0
  316. package/dist-pkg/ui/libras-avatar-player.d.ts +28 -0
  317. package/dist-pkg/ui/libras-avatar-player.js +226 -0
  318. package/dist-pkg/ui/libras-avatar-stage.d.ts +37 -0
  319. package/dist-pkg/ui/libras-avatar-stage.js +208 -0
  320. package/dist-pkg/ui/libras-glosses.d.ts +28 -0
  321. package/dist-pkg/ui/libras-glosses.js +161 -0
  322. package/dist-pkg/ui/locale-flags.d.ts +16 -0
  323. package/dist-pkg/ui/locale-flags.js +30 -0
  324. package/dist-pkg/ui/loop-crash.d.ts +17 -17
  325. package/dist-pkg/ui/loop-crash.js +33 -62
  326. package/dist-pkg/ui/menu-intent.d.ts +61 -0
  327. package/dist-pkg/ui/menu-intent.js +88 -0
  328. package/dist-pkg/ui/menu-items.d.ts +20 -0
  329. package/dist-pkg/ui/menu-items.js +51 -0
  330. package/dist-pkg/ui/menu-nav.d.ts +98 -92
  331. package/dist-pkg/ui/menu-nav.js +398 -286
  332. package/dist-pkg/ui/mobility-choices.d.ts +26 -0
  333. package/dist-pkg/ui/mobility-choices.js +41 -0
  334. package/dist-pkg/ui/motion-choices.d.ts +31 -0
  335. package/dist-pkg/ui/motion-choices.js +68 -0
  336. package/dist-pkg/ui/motion-scene.d.ts +24 -19
  337. package/dist-pkg/ui/motion-scene.js +29 -61
  338. package/dist-pkg/ui/mount-panel.d.ts +81 -0
  339. package/dist-pkg/ui/mount-panel.js +61 -0
  340. package/dist-pkg/ui/panel-shell.d.ts +65 -31
  341. package/dist-pkg/ui/panel-shell.js +92 -66
  342. package/dist-pkg/ui/panel-widgets.d.ts +150 -0
  343. package/dist-pkg/ui/panel-widgets.js +294 -0
  344. package/dist-pkg/ui/pause-buttons.d.ts +35 -0
  345. package/dist-pkg/ui/pause-buttons.js +66 -0
  346. package/dist-pkg/ui/pause-icons.d.ts +261 -347
  347. package/dist-pkg/ui/pause-icons.js +671 -601
  348. package/dist-pkg/ui/pause-markup.d.ts +86 -0
  349. package/dist-pkg/ui/pause-markup.js +125 -0
  350. package/dist-pkg/ui/reach-notice.d.ts +22 -23
  351. package/dist-pkg/ui/reach-notice.js +55 -58
  352. package/dist-pkg/ui/scan-overlay.d.ts +23 -0
  353. package/dist-pkg/ui/scan-overlay.js +50 -0
  354. package/dist-pkg/ui/screen-text.d.ts +25 -0
  355. package/dist-pkg/ui/screen-text.js +152 -0
  356. package/dist-pkg/ui/session-clock.d.ts +32 -0
  357. package/dist-pkg/ui/session-clock.js +67 -0
  358. package/dist-pkg/ui/settings-aac.d.ts +70 -0
  359. package/dist-pkg/ui/settings-aac.js +208 -0
  360. package/dist-pkg/ui/settings-audio.d.ts +97 -114
  361. package/dist-pkg/ui/settings-audio.js +493 -425
  362. package/dist-pkg/ui/settings-controls.d.ts +53 -96
  363. package/dist-pkg/ui/settings-controls.js +143 -215
  364. package/dist-pkg/ui/settings-empathy.d.ts +39 -30
  365. package/dist-pkg/ui/settings-empathy.js +53 -60
  366. package/dist-pkg/ui/settings-mobility.d.ts +192 -0
  367. package/dist-pkg/ui/settings-mobility.js +332 -0
  368. package/dist-pkg/ui/settings-motion.d.ts +91 -70
  369. package/dist-pkg/ui/settings-motion.js +287 -198
  370. package/dist-pkg/ui/settings-panel.d.ts +58 -45
  371. package/dist-pkg/ui/settings-panel.js +189 -94
  372. package/dist-pkg/ui/settings-typo.d.ts +29 -78
  373. package/dist-pkg/ui/settings-typo.js +158 -129
  374. package/dist-pkg/ui/settings-visual.d.ts +29 -87
  375. package/dist-pkg/ui/settings-visual.js +240 -193
  376. package/dist-pkg/ui/shell.d.ts +112 -135
  377. package/dist-pkg/ui/shell.js +148 -217
  378. package/dist-pkg/ui/simulation-list.d.ts +27 -0
  379. package/dist-pkg/ui/simulation-list.js +76 -0
  380. package/dist-pkg/ui/simulation-over-the-world.d.ts +23 -0
  381. package/dist-pkg/ui/simulation-over-the-world.js +131 -0
  382. package/dist-pkg/ui/simulation-refusal.d.ts +5 -31
  383. package/dist-pkg/ui/simulation-refusal.js +8 -56
  384. package/dist-pkg/ui/switchable-control.d.ts +11 -0
  385. package/dist-pkg/ui/switchable-control.js +19 -0
  386. package/dist-pkg/ui/title.d.ts +3 -12
  387. package/dist-pkg/ui/title.js +49 -18
  388. package/dist-pkg/ui/top-band.d.ts +26 -0
  389. package/dist-pkg/ui/top-band.js +96 -0
  390. package/dist-pkg/ui/typo-choices.d.ts +71 -0
  391. package/dist-pkg/ui/typo-choices.js +85 -0
  392. package/dist-pkg/ui/visual-axes-panel.d.ts +11 -47
  393. package/dist-pkg/ui/visual-axes-panel.js +12 -94
  394. package/dist-pkg/ui/visual-choices.d.ts +77 -0
  395. package/dist-pkg/ui/visual-choices.js +107 -0
  396. package/dist-pkg/ui/vlibras.d.ts +77 -10
  397. package/dist-pkg/ui/vlibras.js +130 -81
  398. package/dist-pkg/ui/voice-control.d.ts +68 -0
  399. package/dist-pkg/ui/voice-control.js +276 -0
  400. package/dist-pkg/ui/voice-settings.d.ts +95 -0
  401. package/dist-pkg/ui/voice-settings.js +352 -0
  402. package/dist-pkg/ui/where-the-child-is.d.ts +31 -0
  403. package/dist-pkg/ui/where-the-child-is.js +70 -0
  404. package/docs/CREDITS.md +300 -44
  405. package/docs/LICENSES.md +189 -145
  406. package/package.json +51 -27
  407. package/scripts/check-cartridge.mjs +78 -0
  408. package/scripts/game-build.d.mts +25 -0
  409. package/scripts/game-build.mjs +144 -0
  410. package/scripts/heavy-into-the-delivery.mjs +388 -0
  411. package/scripts/libras-avatar.json +680 -0
  412. package/scripts/libras-avatar.mjs +246 -0
  413. package/scripts/libras-glosses/gloss.py +95 -0
  414. package/scripts/libras-glosses/pyproject.toml +32 -0
  415. package/scripts/libras-glosses/uv.lock +781 -0
  416. package/scripts/libras-glosses.mjs +351 -0
  417. package/scripts/licences/Apache-2.0.txt +176 -0
  418. package/scripts/licences/GPL-3.0.txt +674 -0
  419. package/scripts/licences/MIT.txt +17 -0
  420. package/scripts/licences/OFL-1.1.txt +86 -0
  421. package/scripts/licences/UFL-1.0.txt +96 -0
  422. package/scripts/licences/fonts.mjs +389 -0
  423. package/scripts/licences/third-party.mjs +301 -0
  424. package/scripts/licences/vosk-browser.NOTICE.txt +268 -0
  425. package/app/public/vendor/fonts/comicneue-400.woff2 +0 -0
  426. package/app/public/vendor/fonts/comicneue-700.woff2 +0 -0
  427. package/app/public/vendor/fonts/fondamento-400-ext.woff2 +0 -0
  428. package/app/public/vendor/fonts/fondamento-400.woff2 +0 -0
  429. package/app/public/vendor/fonts/inter-400.woff2 +0 -0
  430. package/app/public/vendor/fonts/inter-700.woff2 +0 -0
  431. package/app/public/vendor/fonts/lato-400.woff2 +0 -0
  432. package/app/public/vendor/fonts/lato-700.woff2 +0 -0
  433. package/app/public/vendor/fonts/literata-400.woff2 +0 -0
  434. package/app/public/vendor/fonts/literata-700.woff2 +0 -0
  435. package/app/public/vendor/fonts/newsreader-400.woff2 +0 -0
  436. package/app/public/vendor/fonts/newsreader-700.woff2 +0 -0
  437. package/app/public/vendor/fonts/opendyslexic-400.woff2 +0 -0
  438. package/app/public/vendor/fonts/opensans-400.woff2 +0 -0
  439. package/app/public/vendor/fonts/opensans-700.woff2 +0 -0
  440. package/app/public/vendor/fonts/pinyon-400.woff2 +0 -0
  441. package/app/public/vendor/fonts/pressstart-400.woff2 +0 -0
  442. package/app/public/vendor/fonts/quattro-400.woff2 +0 -0
  443. package/app/public/vendor/fonts/quattro-700.woff2 +0 -0
  444. package/app/public/vendor/fonts/sourcesans-400.woff2 +0 -0
  445. package/app/public/vendor/fonts/sourcesans-700.woff2 +0 -0
  446. package/app/public/vendor/fonts/sourceserif-400.woff2 +0 -0
  447. package/app/public/vendor/fonts/sourceserif-700.woff2 +0 -0
  448. package/app/public/vendor/fonts/ufmag-400.woff2 +0 -0
  449. package/dist-pkg/core/anel.d.ts +0 -17
  450. package/dist-pkg/core/anel.js +0 -31
  451. package/dist-pkg/core/collision.d.ts +0 -21
  452. package/dist-pkg/core/collision.js +0 -62
  453. package/dist-pkg/core/layers.d.ts +0 -63
  454. package/dist-pkg/core/layers.js +0 -95
  455. package/dist-pkg/core/letter-grid.d.ts +0 -55
  456. package/dist-pkg/core/letter-grid.js +0 -116
  457. package/dist-pkg/core/password.d.ts +0 -34
  458. package/dist-pkg/core/password.js +0 -205
  459. package/dist-pkg/core/rotulo-acessivel.d.ts +0 -17
  460. package/dist-pkg/core/rotulo-acessivel.js +0 -41
  461. package/dist-pkg/core/run-state.d.ts +0 -115
  462. package/dist-pkg/core/run-state.js +0 -40
  463. package/dist-pkg/core/tiles.d.ts +0 -12
  464. package/dist-pkg/core/tiles.js +0 -61
  465. package/dist-pkg/core/world.d.ts +0 -4
  466. package/dist-pkg/core/world.js +0 -58
  467. package/dist-pkg/input/origem-sintetica.d.ts +0 -44
  468. package/dist-pkg/input/origem-sintetica.js +0 -60
  469. package/dist-pkg/input/transporte-em-uso.d.ts +0 -101
  470. package/dist-pkg/input/transporte-em-uso.js +0 -130
  471. package/dist-pkg/platform/audio-nav.d.ts +0 -51
  472. package/dist-pkg/platform/audio-nav.js +0 -99
  473. package/dist-pkg/platform/guide-intensity.d.ts +0 -40
  474. package/dist-pkg/platform/guide-intensity.js +0 -73
  475. package/dist-pkg/platform/pesados-catalogo.d.ts +0 -14
  476. package/dist-pkg/platform/pesados-catalogo.js +0 -177
  477. package/dist-pkg/platform/pesados.d.ts +0 -31
  478. package/dist-pkg/platform/pesados.js +0 -75
  479. package/dist-pkg/platform/vozes-prontas.d.ts +0 -28
  480. package/dist-pkg/platform/vozes-prontas.js +0 -61
  481. package/dist-pkg/render/camera.d.ts +0 -58
  482. package/dist-pkg/render/camera.js +0 -105
  483. package/dist-pkg/render/cenario-data.d.ts +0 -127
  484. package/dist-pkg/render/cenario-data.js +0 -145
  485. package/dist-pkg/render/city-tex.d.ts +0 -63
  486. package/dist-pkg/render/city-tex.js +0 -228
  487. package/dist-pkg/render/city-tiles.d.ts +0 -11
  488. package/dist-pkg/render/city-tiles.js +0 -140
  489. package/dist-pkg/render/draw.d.ts +0 -149
  490. package/dist-pkg/render/draw.js +0 -231
  491. package/dist-pkg/render/fx.d.ts +0 -63
  492. package/dist-pkg/render/fx.js +0 -123
  493. package/dist-pkg/render/minimap.d.ts +0 -11
  494. package/dist-pkg/render/minimap.js +0 -94
  495. package/dist-pkg/render/parallax.d.ts +0 -85
  496. package/dist-pkg/render/parallax.js +0 -158
  497. package/dist-pkg/render/player-anim.d.ts +0 -71
  498. package/dist-pkg/render/player-anim.js +0 -152
  499. package/dist-pkg/render/recycling-tex.d.ts +0 -48
  500. package/dist-pkg/render/recycling-tex.js +0 -164
  501. package/dist-pkg/render/scene-city.d.ts +0 -77
  502. package/dist-pkg/render/scene-city.js +0 -181
  503. package/dist-pkg/render/scene-parallax.d.ts +0 -72
  504. package/dist-pkg/render/scene-parallax.js +0 -426
  505. package/dist-pkg/render/scene-sky.d.ts +0 -126
  506. package/dist-pkg/render/scene-sky.js +0 -295
  507. package/dist-pkg/render/set-cenario.d.ts +0 -54
  508. package/dist-pkg/render/set-cenario.js +0 -103
  509. package/dist-pkg/render/textures.d.ts +0 -75
  510. package/dist-pkg/render/textures.js +0 -240
  511. package/dist-pkg/render/title-scene.d.ts +0 -46
  512. package/dist-pkg/render/title-scene.js +0 -75
  513. package/dist-pkg/render/weather.d.ts +0 -96
  514. package/dist-pkg/render/weather.js +0 -171
  515. package/dist-pkg/render/wheelchair-sprites.d.ts +0 -32
  516. package/dist-pkg/render/wheelchair-sprites.js +0 -69
  517. package/dist-pkg/render/world-tex.d.ts +0 -18
  518. package/dist-pkg/render/world-tex.js +0 -87
  519. package/dist-pkg/ui/activities-menu.d.ts +0 -258
  520. package/dist-pkg/ui/activities-menu.js +0 -648
  521. package/dist-pkg/ui/caa-sets.d.ts +0 -39
  522. package/dist-pkg/ui/caa-sets.js +0 -65
  523. package/dist-pkg/ui/latch-refusal.d.ts +0 -32
  524. package/dist-pkg/ui/latch-refusal.js +0 -60
  525. package/dist-pkg/ui/map-hub.d.ts +0 -56
  526. package/dist-pkg/ui/map-hub.js +0 -138
  527. package/dist-pkg/ui/settings-caa.d.ts +0 -45
  528. package/dist-pkg/ui/settings-caa.js +0 -137
  529. package/dist-pkg/ui/settings-motor.d.ts +0 -175
  530. package/dist-pkg/ui/settings-motor.js +0 -342
  531. package/dist-pkg/ui/webcam.d.ts +0 -7
  532. package/dist-pkg/ui/webcam.js +0 -93
@@ -1,29 +1,27 @@
1
1
  // SPDX-License-Identifier: AGPL-3.0-or-later
2
2
  import type { Action } from './actions.js';
3
- import type { VisualState } from '../render/viz-axes.js';
3
+ import type { VisualState } from './visual-state.js';
4
4
  /**
5
- * Ação → lista de códigos físicos (`KeyA`, `ArrowLeft`…). Fonte única: estava triplicado em input/.
5
+ * Action → list of physical codes (`KeyA`, `ArrowLeft`…). The single source: it was written three times in input/.
6
6
  *
7
- * ⚠️ FECHADO EM `Action` DESDE 2026-09-07 (issue #118, decisão do Dev), e era `Record<string, string[]>`.
8
- * Enquanto foi aberto, **faltar uma posição não dava erro de compilação** — e foi assim que o esquema de
9
- * dupla ficou com oito das quatorze, e que a `Space` do jogador 1 desapareceu sem que nada apitasse. O
10
- * defeito não era de digitação: era de o tipo aceitar um esquema incompleto como se fosse completo.
7
+ * ⚠️ CLOSED OVER `Action` (issue #118, the Dev's decision); it was `Record<string, string[]>`. While it was open,
8
+ * **a missing position was no compile error** — that is how a two-player scheme ended up with eight of the fourteen and
9
+ * player 1's `Space` vanished with nothing going off. The defect was not a typo: the type accepted an incomplete scheme
10
+ * as complete.
11
11
  *
12
- * ⚠️ E `null` NÃO É BURACO — é AUSÊNCIA DECLARADA, e é a metade que dá sentido a fechar o tipo. Um teclado
13
- * partido por quatro pode não ter lugar físico para ombros e gatilhos; dizer `null` afirma isso, e é o que o
14
- * aviso de alcance (`ui/reach-notice`, issue #112) lê para dizer à criança, ANTES de ela começar, quais das
15
- * ações do jogo o controlo dela não alcança. Inventar teclas para preencher seria mentir-lhe em silêncio.
12
+ * ⚠️ AND `null` IS NOT A HOLE — it is a DECLARED ABSENCE, the half that gives closing the type its meaning. A keyboard
13
+ * split four ways may have no physical room for shoulders and triggers; `null` says so, and it is what the reach notice
14
+ * (`ui/reach-notice`, issue #112) reads to tell the child, BEFORE they start, which of the game's actions their
15
+ * controls cannot reach. Inventing keys to fill it would lie to them in silence.
16
16
  *
17
- * Quem consome tem de tratar o `null`: `input/keyboard-runtime`, `input/touch-bindings` e
18
- * `ui/settings-controls` fazem-no, e é isso que impede um `null` de virar um `undefined.includes`.
17
+ * Consumers have to handle the `null`, and that is what keeps a `null` from becoming an `undefined.includes`.
19
18
  */
20
19
  export type KeyScheme = Record<Action, readonly string[] | null>;
21
- /** Lados da ventosa-aranha: direita, esquerda, teto, chão. */
20
+ /** The sides a clinging player can stick to: right, left, ceiling, floor. */
22
21
  export type ClingSide = 'R' | 'L' | 'U' | 'D';
23
22
  /**
24
- * O sprite do jogador visto pelo jogo: posição, opacidade, escala e textura. Mesma forma que render/draw
25
- * declara como `PlayerSprite` — é um PIXI.Sprite reduzido ao que o jogo escreve nele, de propósito, para que
26
- * a lógica rode no project `node` com um sprite de mentira.
23
+ * The player's sprite as the game sees it: position, opacity, scale and texture. A PIXI.Sprite reduced to what the
24
+ * game writes on it, on purpose, so the logic runs in the `node` project with a fake sprite.
27
25
  */
28
26
  export interface PlayerSpriteLike {
29
27
  x: number;
@@ -36,13 +34,12 @@ export interface PlayerSpriteLike {
36
34
  texture: unknown;
37
35
  }
38
36
  /**
39
- * O JOGADOR. Os campos até `_swapSonar` são os que `game/player.makePlayer` cria — todos obrigatórios, porque
40
- * a fábrica sempre os escreve. Depois vêm os que outros subsistemas ACRESCENTAM em tempo de execução, e esses
41
- * são opcionais porque um jogador recém-criado genuinamente não os tem.
37
+ * THE PLAYER. The fields down to `_swapSonar` are the ones the player factory creates — all required, because the
38
+ * factory always writes them. After them come the ones other subsystems ADD at run time, optional because a freshly
39
+ * made player genuinely does not have them.
42
40
  *
43
- * A distinção não é cosmética: hoje `physics` exige `elevTarget` como opcional e `gamepad` exige `quit` como
44
- * obrigatório, e as duas leem o MESMO objeto. Escrever de que lado da linha cada campo cai é metade do valor
45
- * deste arquivo.
41
+ * The split is not cosmetic: two modules reading the SAME object used to disagree about which side of this line a
42
+ * field falls on. Writing it down is half the value of this file.
46
43
  */
47
44
  export interface Player {
48
45
  i: number;
@@ -54,7 +51,7 @@ export interface Player {
54
51
  onLadder: boolean;
55
52
  inWater: boolean;
56
53
  clinging: boolean;
57
- /** Face à qual a ventosa-aranha está grudada; `null` quando não está grudado. */
54
+ /** The side the player is clinging to; `null` when not clinging. */
58
55
  clingN: ClingSide | null;
59
56
  flying: boolean;
60
57
  airTime: number;
@@ -67,7 +64,7 @@ export interface Player {
67
64
  groundIdle: number;
68
65
  flavor: number;
69
66
  flavorT: number;
70
- /** Quadro corrente. `Frame` é `unknown` em render/player-anim — a textura é opaca para o jogo. */
67
+ /** The current frame. Opaque to the game — the texture is the renderer's business. */
71
68
  _tx: unknown;
72
69
  jumpBuffer: number;
73
70
  jumpChain: number;
@@ -85,45 +82,37 @@ export interface Player {
85
82
  activePower: string;
86
83
  hasKey: boolean;
87
84
  /**
88
- * Esquema de teclas. `makePlayer` nasce com `null` e `assignControls` preenche no boot — por isso o `| null`.
89
- * `game/physics` e `input/keyboard-runtime` declaram este campo como NÃO-nulo, o que é verdade no instante
90
- * em que eles rodam mas não é verdade no tipo. Divergência REAL, deixada visível aqui de propósito em vez de
91
- * apagada: quem estreitar precisa fazê-lo explicitamente, no ponto onde sabe que já foi atribuído.
85
+ * The key scheme. A player is born with `null` and `assignControls` fills it at boot — hence the `| null`. Modules
86
+ * that only run after boot may treat it as non-null, which is true at that instant but not in the type: a REAL
87
+ * divergence, left visible on purpose — whoever narrows it does so explicitly, where they know it was assigned.
92
88
  */
93
89
  ctrl: KeyScheme | null;
94
- /** Índice do gamepad, ou -1 quando o jogador não tem controle físico. */
90
+ /** The gamepad index, or -1 when the player has no physical pad. */
95
91
  pad: number;
96
92
  /**
97
- * O ESTADO VISUAL desta criança, em DOIS EIXOS mais a simulação (ADR-0076, issue #104).
93
+ * This child's VISUAL STATE, in TWO AXES plus the simulation (ADR-0076, issue #104).
98
94
  *
99
- * ⚠️ `import type`, e a seta aponta para cima. `core/` não deveria importar de `render/`, e o tipo do
100
- * ESTADO discutivelmente devia morar aqui em vez de lá. Fica assim de propósito e declarado: é só tipo,
101
- * apagado em execução, sem aresta em runtime — e mover o módulo a meio da migração seria churn no ficheiro
102
- * mais partilhado do repositório. Se `viz-axes` se dividir um dia, o `VisualState` vem para `core/` e as
103
- * funções de renderização ficam lá.
95
+ * The shape lives in `core/visual-state`; `render/viz-axes` applies it (issue #167).
104
96
  */
105
97
  visual: VisualState;
106
98
  /**
107
- * @deprecated ⚠️ O ESPELHO LEGADO, e ele morre nesta migração. Enquanto os dois existirem, `setPlayerViz`
108
- * escreve os DOIS e um gate exige que nunca discordem — é o que deixa cada leitor migrar sozinho, com a
109
- * árvore verde entre cada passo, em vez de uma passagem única onde não há onde parar.
99
+ * @deprecated ⚠️ THE LEGACY MIRROR, and it dies in this migration. While both exist, `setPlayerViz` writes BOTH and a
100
+ * gate requires they never disagree — that lets each reader migrate on its own, with the tree green between steps.
110
101
  *
111
- * ⚠️ E ELE NÃO CONSEGUE EXPRIMIR O QUE A #104 EXISTE PARA PERMITIR: uma criança com `hc7` E `fix-deuter` ao
112
- * mesmo tempo não tem chave única que a descreva. Por isso o espelho só sobrevive enquanto os controles
113
- * ainda escrevem um valor de cada vez; assim que eles passam a escrever por eixo, ele deixa de poder
114
- * acompanhar e sai.
102
+ * ⚠️ AND IT CANNOT EXPRESS WHAT #104 EXISTS TO ALLOW: a child with `hc7` AND a colour correction at once has no single
103
+ * key describing them. So the mirror survives only while the controls still write one value at a time.
115
104
  */
116
105
  viz: string;
117
106
  easy: boolean;
118
107
  toggleMove: boolean;
119
108
  /**
120
- * A ALTERNÂNCIA DO BOTÃO DE CORRER (pedido do Dev): correr vira ESTADO em vez de "segurar".
109
+ * THE RUN-BUTTON TOGGLE (asked for by the Dev): running becomes a STATE instead of "holding".
121
110
  *
122
- * Irmã de `toggleMove` e pelo mesmo motivo — quem não consegue manter pressionado andava sem segurar e
123
- * continuava sem conseguir CORRER. Automática no controle de toque. Ver `game/run-toggle`.
111
+ * Sibling of `toggleMove` for the same reason — whoever cannot keep a button held could walk without holding and
112
+ * still could not RUN. Automatic on the touch pad.
124
113
  */
125
114
  toggleRun: boolean;
126
- /** A trava da corrida: com `toggleRun`, é ela que diz se está correndo agora. Vida de RODADA. */
115
+ /** The run latch: with `toggleRun`, it says whether the player is running now. Lives for a ROUND. */
127
116
  runLatch: boolean;
128
117
  rmWalk: boolean;
129
118
  rmBreath: boolean;
@@ -134,60 +123,56 @@ export interface Player {
134
123
  _swapT: number;
135
124
  _swapSonar: boolean;
136
125
  sprite: PlayerSpriteLike | null;
137
- /** ui/shell, input/gamepad, ui/hud: o jogador pediu para sair. */
126
+ /** The player asked to quit. */
138
127
  quit?: boolean;
139
- /** game/session: entrou no meio da partida e aguarda a próxima rodada. */
128
+ /** Joined mid-game and waits for the next round. */
140
129
  waiting?: boolean;
141
- /** game/level-geometry, game/physics: andar de destino do elevador em que está. */
130
+ /** The target floor of the lift the player is on. */
142
131
  elevTarget?: number | null;
143
- /** game/physics: velocidade de queda memorizada para o som de impacto. */
132
+ /** The fall speed remembered for the landing sound. */
144
133
  _fallV?: number;
145
- /** game/physics: distância pisada desde a última batida de bengala. */
134
+ /** The distance walked since the last cane tap. */
146
135
  caneDist?: number;
147
- /** game/session, render/player-anim: usa a bengala de corrida (o cego só corre com ela). */
136
+ /** Uses the running cane (a blind player only runs with it). */
148
137
  runCane?: boolean;
149
- /** render/fx → render/draw: fator de esmagamento (squash) e o temporizador que o decai (8 → 0).
150
- * Os dois ANDAM JUNTOS — `stepSquash` escreve os dois e `drawPlayers` lê os dois. Declarar só o `sq`, como
151
- * esta interface fazia até a conferência no navegador, é o erro de meia-dupla: o campo que sobra fica sem
152
- * tipo nenhum e ninguém percebe, porque metade da regra continua compilando. */
138
+ /** The squash factor and the timer that decays it (8 → 0). The two GO TOGETHER — one step writes both and the
139
+ * drawing reads both. Declaring only `sq` is the half-pair mistake: the field left over has no type at all and
140
+ * nobody notices, because half the rule still compiles. */
153
141
  sq?: number;
154
142
  sqT?: number;
155
- /** render/player-anim → render/draw: o jogador está andando / correndo. Derivados por quadro a partir da
156
- * velocidade e do estado de contato; existem porque a BENGALA precisa saber (a de corrida só aparece
157
- * correndo, e correr exige `runCane`). Escritos pelo render, nunca pela fábrica. */
143
+ /** The player is walking / running. Derived each frame from speed and contact; they exist because the CANE needs to
144
+ * know (the running cane only shows when running, and running needs `runCane`). Written by the renderer, never by
145
+ * the factory. */
158
146
  walking?: boolean;
159
147
  running?: boolean;
160
- /** game/quiz: vitórias na atividade de alfabetização, zeradas a cada nova partida. */
161
- alfWins?: number;
162
- /** ui/settings-audio, ui/pause-icons: saída de áudio própria; `null`/ausente = compartilhada. */
148
+ /** Wins in the literacy activity, reset at each new game. */
149
+ literacyWins?: number;
150
+ /** The player's own audio output; `null`/absent = shared. */
163
151
  audioSink?: string | null;
164
152
  /**
165
- * platform/audio-nav: temporizador do sonar de parede.
153
+ * The wall-sonar timer, read by the platformer's `platform/audio-nav` (moved there in note CC).
166
154
  *
167
- * ⚠️ `guideT` SAIU em 2026-09-07 (#84 item 2), e a ausência é a notícia: ele contava os 48 quadros entre
168
- * dois bipes do guia, e não há mais bipe nenhum para temporizar. O que o substituiu — o grafo de áudio vivo
169
- * — não é da entidade da engine e por isso não nasce aqui: mora em `PlayerAudioOut`, ao lado do `_ac`, pela
170
- * mesma regra que o parágrafo acima explica.
155
+ * ⚠️ `guideT` is gone (#84 item 2): it counted the frames between two guide beeps, and there is no beep left to time.
156
+ * What replaced it — the live audio graph — is not the engine entity's and so is not born here: it lives in
157
+ * `PlayerAudioOut`, beside `_ac`, by the rule the paragraph above explains.
171
158
  */
172
159
  wnT?: number;
173
160
  }
174
161
  /**
175
- * Um jogador DEPOIS de `assignControls` — o `ctrl` deixou de ser `null`.
162
+ * A player AFTER `assignControls` — `ctrl` is no longer `null`.
176
163
  *
177
- * Existe para dar nome a uma invariante que hoje é assumida em silêncio: `game/physics` e
178
- * `input/keyboard-runtime` declaram `ctrl` como não-nulo porque, no instante em que rodam, ele já foi
179
- * atribuído. Isso é verdade e continua verdade — mas era uma afirmação escondida dentro de uma interface
180
- * redigitada, onde ninguém a lia como afirmação. Aqui ela tem nome, e quem a usa está dizendo "eu só rodo
181
- * depois do boot", que é uma frase verificável, em vez de simplesmente não mencionar o `null`.
164
+ * It names an invariant otherwise assumed in silence: modules that only run after boot treat `ctrl` as non-null. That
165
+ * is true — but it was an assertion hidden inside a retyped interface, where nobody read it as one. Here it has a name,
166
+ * and whoever uses it is saying "I only run after boot", a checkable sentence, instead of not mentioning the `null`.
182
167
  */
183
168
  export type ControlledPlayer = Player & {
184
169
  ctrl: KeyScheme;
185
170
  };
186
171
  /**
187
- * Atalho para as visões estreitas: `PlayerView<'x' | 'y'>` em vez de reescrever os campos.
172
+ * A shortcut for the narrow views: `PlayerView<'x' | 'y'>` instead of rewriting the fields.
188
173
  *
189
- * O ponto de não usar `Player` inteiro está no cabeçalho: o project `node` do Vitest monta jogadores de
190
- * mentira com só os campos que o módulo lê, e uma interface gorda obrigaria todo fixture a inventar 52.
191
- * Derivando, o módulo continua acoplado à sua fatia e o NOME e o TIPO de cada campo passam a ter fonte única.
174
+ * The point of not using the whole `Player` is in the header: the Vitest `node` project builds fake players with only
175
+ * the fields a module reads, and a fat interface would make every fixture invent all of them. Deriving keeps the module
176
+ * coupled to its slice while each field's NAME and TYPE have one source.
192
177
  */
193
178
  export type PlayerView<K extends keyof Player> = Pick<Player, K>;
@@ -1,38 +1,24 @@
1
1
  // SPDX-License-Identifier: AGPL-3.0-or-later
2
- // core/entity — O JOGADOR, escrito UMA vez. Passo 1 do ADR-0027, e o único que o ADR chama de pré-requisito
3
- // de todos os outros. Não move nada e não muda nada em tempo de execução: `tsc --noEmit` é o teste inteiro.
2
+ // core/entity — THE PLAYER, written ONCE. Step 1 of ADR-0027, the one that record calls the prerequisite of all the
3
+ // others. It moves nothing and changes nothing at run time: `tsc --noEmit` is its whole test.
4
4
  //
5
- // O PROBLEMA QUE ISTO RESOLVE. `core/state.players` é `unknown[]`. O tipo se perde exatamente na fronteira em
6
- // que a entidade atravessa o programa, então cada módulo que precisa de um jogador escreveu à mão a sua
7
- // própria visão estrutural e fez cast. São VINTE E TRÊS — o ADR-0027 estimou dez, contei uma a uma e são 23 —
8
- // e elas já não concordam entre si:
5
+ // THE PROBLEM THIS SOLVES. `core/state.players` is `unknown[]`. The type is lost exactly at the boundary where the
6
+ // entity crosses the program, so every module that needed a player wrote its own structural view by hand and cast.
7
+ // There were twenty-three, and they no longer agreed: the same field required in one module and optional in another
8
+ // for the SAME object, so a player was accepted by half the program and rejected by the other half. That is the
9
+ // failure that already cost a broken climb in Easy mode, when three copies of the action→edge table diverged: a copy
10
+ // nobody forces to agree, diverges.
9
11
  //
10
- // · `quiz` tem QUATRO formas: `unknown` (physics, session, touch), `Quiz | null` (quiz),
11
- // `{ kind: string } | null` (gamepad) e `{ kind?: string } | null` (keydown). O `kind` é obrigatório numa
12
- // e opcional na outra, para o MESMO objeto.
13
- // · `easy` é obrigatório em physics, gamepad e settings-motor; opcional em session, keydown, touch-bindings
14
- // e draw. Um jogador sem `easy` é aceito por metade do programa e rejeitado pela outra.
15
- // · `jumpEdge`, idem: obrigatório em physics/gamepad/attract, opcional em session/keydown/touch-bindings.
16
- // · `quit` é obrigatório em gamepad e hud, opcional em session. `toggleMove` é obrigatório em
17
- // settings-motor, opcional em pause-icons. `viz` é obrigatório em draw, opcional em pause-icons.
18
- // · `KeyScheme` (= `Record<string, string[]>`) está declarado três vezes: em input/keyboard-runtime,
19
- // input/keyboard e input/keydown.
12
+ // HOW IT IS USED — and why modules must NOT import the whole `Player`. What makes the project testable in the Vitest
13
+ // `node` project is that each module declares the MINIMAL slice it needs and the test builds a fake with only those
14
+ // fields. Swapping the narrow views for one fat interface would destroy that: every fixture would have to invent every
15
+ // field.
20
16
  //
21
- // Nada disso é hipótese sobre o futuro: é a mesma forma de falha que já custou uma escalada quebrada no modo
22
- // Fácil, quando três cópias da tabela ação→borda divergiram. Uma cópia que ninguém obriga a concordar diverge.
17
+ // The way out is to derive instead of retyping: `Pick<Player, 'x' | 'y' | 'vx'>` instead of rewriting three fields.
18
+ // The module stays coupled only to its slice and the test still builds only that — but each field's NAME and TYPE have
19
+ // one source, and renaming a field breaks every consumer's compilation at the same instant.
23
20
  //
24
- // COMO ISTO É USADO — e por que os módulos NÃO devem importar `Player` inteiro. A propriedade que faz o
25
- // projeto testável no project `node` do Vitest é que cada módulo declara a fatia MÍNIMA de que precisa e o
26
- // teste monta um objeto de mentira com só aqueles campos. Trocar 23 visões estreitas por uma interface gorda
27
- // destruiria isso: todo fixture de teste passaria a ter de inventar 52 campos.
28
- //
29
- // A saída é derivar em vez de redigitar: `Pick<Player, 'x' | 'y' | 'vx'>` em vez de reescrever os três campos.
30
- // O módulo continua acoplado só à sua fatia; o teste continua montando só aquilo; mas o NOME e o TIPO de cada
31
- // campo passam a ter uma fonte única, e renomear um campo quebra a compilação de todos os consumidores no
32
- // mesmo instante, que é precisamente o que hoje não acontece.
33
- //
34
- // A FRONTEIRA DE CAMADA. `core/` não pode importar de `game/` nem de `render/` — seria inverter a dependência.
35
- // Por isso os campos que apontam para outras camadas entram aqui pelo MÍNIMO ESTRUTURAL: `core` sabe que o
36
- // jogador tem um quiz, não sabe o que é um quiz. Os tipos ricos (`Quiz` em game/quiz, `PlayerSprite` em
37
- // render/draw) são atribuíveis a estes, e é o compilador que garante isso no ponto de uso.
21
+ // THE LAYER BOUNDARY. `core/` may not import upward (ADR-0173), so fields that point at other layers enter here as the
22
+ // STRUCTURAL MINIMUM: the rich types (a sprite in `render/`) are assignable to these, and the compiler checks it where
23
+ // they are used.
38
24
  export {};
@@ -1,16 +1,15 @@
1
1
  // SPDX-License-Identifier: AGPL-3.0-or-later
2
2
  /**
3
- * Os CINCO caracteres, e cobre os dois contextos: elemento (`<` `>`) e ATRIBUTO (`"` `'`).
3
+ * The FIVE characters, covering both contexts: element (`<` `>`) and ATTRIBUTE (`"` `'`).
4
4
  *
5
- * O atributo é o que costuma faltar, e é o pior: dentro de um elemento uma aspa é inofensiva; dentro de
6
- * `aria-label="…"` ela FECHA o atributo e o que vem a seguir vira atributo — um `onmouseover` sem precisar de
7
- * uma única tag.
5
+ * The attribute is the one usually missing, and the worst: inside an element a quote is harmless; inside
6
+ * `aria-label="…"` it CLOSES the attribute and what follows becomes an attribute — an `onmouseover` without a single tag.
8
7
  *
9
- * ⚠️ O `&` É O PRIMEIRO, E A ORDEM É O DEFEITO CLÁSSICO DESTE AJUDANTE. Escapando-o por último, o `&` do
10
- * `&lt;` que acabou de ser produzido é escapado outra vez e a tela mostra `&lt;` literal. É silencioso porque
11
- * quem testa só com `<b>` nunca o vê: a saída ainda «parece» escapada.
8
+ * ⚠️ `&` GOES FIRST, AND THE ORDER IS THIS HELPER'S CLASSIC DEFECT. Escaped last, the `&` of the `&lt;` just produced is
9
+ * escaped again and the screen shows a literal `&lt;`. It is silent because a test with only `<b>` never sees it: the
10
+ * output still "looks" escaped.
12
11
  *
13
- * E ele escapa, não apaga. Apagar mudaria a palavra que a criança digitou, e uma atividade cujo texto muda
14
- * sozinho é um defeito diferente e igualmente sério.
12
+ * And it escapes, it does not delete. Deleting would change the word the child typed, and an activity whose text changes
13
+ * by itself is a different defect, and just as serious.
15
14
  */
16
- export declare function escaparHtml(s: string): string;
15
+ export declare function escapeHtml(s: string): string;
@@ -1,31 +1,27 @@
1
1
  // SPDX-License-Identifier: AGPL-3.0-or-later
2
- // core/escape-html.ts — ESCAPAR TEXTO QUE VAI PARAR EM MARCAÇÃO. Módulo-folha: uma função, zero dependências.
2
+ // core/escape-html.ts — ESCAPING TEXT THAT ENDS UP IN MARKUP. A leaf module: one function, no dependencies.
3
3
  //
4
- // ⚠️ NASCEU DENTRO DE `game/quiz.ts` E TEVE DE SAIR NO DIA SEGUINTE, o que vale registrar porque a razão não
5
- // é arrumação: `game/` é o CARTUCHO, e a issue #111 leva-o para um repositório próprio. O ajudante sairia com
6
- // ele, e o `consumer-quiz` — que é prova da ENGINE — nem sequer pode importar de `game/`, porque o
7
- // `engine-boundary` o proíbe. Um utilitário de segurança que vive do lado errado da fronteira é um utilitário
8
- // que o próximo consumidor reescreve, e duas versões de um escape divergem em silêncio.
4
+ // ⚠️ It lives in the engine, not in a cartridge, because a security helper on the wrong side of a boundary is one the
5
+ // next consumer rewrites — and two versions of an escape diverge in silence.
9
6
  //
10
- // ⚠️ E O ESCAPE É O SEGUNDO RECURSO, NÃO O PRIMEIRO. Onde o valor cabe num nó — `textContent`, `setAttribute`
11
- // —, é assim que ele entra, porque aí não há o que esquecer. Isto existe para o caso em que o texto está
12
- // dentro de um construtor denso de marcação, e nesse caso vem sempre acompanhado de um gate com conteúdo
13
- // hostil: um escape sem rasto é pior do que construir nós.
7
+ // ⚠️ AND ESCAPING IS THE SECOND RESORT, NOT THE FIRST. Where the value fits a node — `textContent`, `setAttribute` —
8
+ // that is how it goes in, because then there is nothing to forget. This exists for text inside a dense markup
9
+ // builder, and there it always comes with a gate fed hostile content: an escape without a trace is worse than
10
+ // building nodes.
14
11
  /**
15
- * Os CINCO caracteres, e cobre os dois contextos: elemento (`<` `>`) e ATRIBUTO (`"` `'`).
12
+ * The FIVE characters, covering both contexts: element (`<` `>`) and ATTRIBUTE (`"` `'`).
16
13
  *
17
- * O atributo é o que costuma faltar, e é o pior: dentro de um elemento uma aspa é inofensiva; dentro de
18
- * `aria-label="…"` ela FECHA o atributo e o que vem a seguir vira atributo — um `onmouseover` sem precisar de
19
- * uma única tag.
14
+ * The attribute is the one usually missing, and the worst: inside an element a quote is harmless; inside
15
+ * `aria-label="…"` it CLOSES the attribute and what follows becomes an attribute — an `onmouseover` without a single tag.
20
16
  *
21
- * ⚠️ O `&` É O PRIMEIRO, E A ORDEM É O DEFEITO CLÁSSICO DESTE AJUDANTE. Escapando-o por último, o `&` do
22
- * `&lt;` que acabou de ser produzido é escapado outra vez e a tela mostra `&lt;` literal. É silencioso porque
23
- * quem testa só com `<b>` nunca o vê: a saída ainda «parece» escapada.
17
+ * ⚠️ `&` GOES FIRST, AND THE ORDER IS THIS HELPER'S CLASSIC DEFECT. Escaped last, the `&` of the `&lt;` just produced is
18
+ * escaped again and the screen shows a literal `&lt;`. It is silent because a test with only `<b>` never sees it: the
19
+ * output still "looks" escaped.
24
20
  *
25
- * E ele escapa, não apaga. Apagar mudaria a palavra que a criança digitou, e uma atividade cujo texto muda
26
- * sozinho é um defeito diferente e igualmente sério.
21
+ * And it escapes, it does not delete. Deleting would change the word the child typed, and an activity whose text changes
22
+ * by itself is a different defect, and just as serious.
27
23
  */
28
- export function escaparHtml(s) {
24
+ export function escapeHtml(s) {
29
25
  return String(s)
30
26
  .replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;')
31
27
  .replaceAll('"', '&quot;').replaceAll("'", '&#39;');
@@ -0,0 +1,17 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ /** The grid: 64×64 cells of a 1024×768 reference. */
3
+ export declare const COLUMNS = 16;
4
+ export declare const ROWS = 12;
5
+ export interface LuminanceFrame {
6
+ /** Milliseconds. */
7
+ readonly t: number;
8
+ /** Relative luminance 0..1 per cell, row by row, `COLUMNS * ROWS` long. */
9
+ readonly luminances: ArrayLike<number>;
10
+ }
11
+ export interface FlashVerdict {
12
+ readonly passes: boolean;
13
+ /** The most general flashes any 10° field showed within one second. */
14
+ readonly worstSecond: number;
15
+ }
16
+ /** Counts general flashes per 10° field and returns the worst second. */
17
+ export declare function analyseFlashes(frames: readonly LuminanceFrame[]): FlashVerdict;
@@ -0,0 +1,113 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // core/flash-threshold — THE GENERAL FLASH THRESHOLD OF WCAG 2.3.1, over a grid of relative luminance (study item B2).
3
+ //
4
+ // ADR-0020 names a FLASH_LIMIT pass and the engine limits nothing a cartridge flashes: it does not own the render. What it
5
+ // can do is MEASURE what a game draws and say it. This file is the pure half — frames in, a verdict out, no DOM, no clock —
6
+ // so the rule is tested by numbers written from the source; the sampler that reads a canvas lives with the root.
7
+ //
8
+ // 📌 THE SOURCE (read 2026-09-13), W3C Understanding SC 2.3.1, WCAG 2.2: a general flash is «a pair of opposing changes in
9
+ // relative luminance of 10% or more of the maximum relative luminance (1.0) where the relative luminance of the darker
10
+ // image is below 0.80»; the threshold passes with «no more than three … within any one-second period» or when the
11
+ // concurrent area is «no more than … .006 steradians within any 10 degree visual field» (341×256 px at 1024×768; 25%).
12
+ // ⚠️ NOT HERE: the red flash (CIE 1976 UCS chromaticity) — a verdict of «passes» from this file says nothing about red.
13
+ // A LEAF: imports nothing.
14
+ /** The grid: 64×64 cells of a 1024×768 reference. */
15
+ export const COLUMNS = 16;
16
+ export const ROWS = 12;
17
+ /** The 10° field as whole cells: 5×4 = 320×256, the nearest rectangle to 341×256. */
18
+ const WINDOW_C = 5;
19
+ const WINDOW_L = 4;
20
+ /** More than 25% of the field: 21 824 px of 87 296, 5.3 cells of 4 096 px — so 6 cells. */
21
+ const CELLS_FOR_AREA = 6;
22
+ const CHANGE = 0.1;
23
+ const DARK_BELOW = 0.8;
24
+ const MAX_PER_SECOND = 3;
25
+ const CELLS = COLUMNS * ROWS;
26
+ const WINDOWS = (COLUMNS - WINDOW_C + 1) * (ROWS - WINDOW_L + 1);
27
+ /**
28
+ * Per cell, a TRANSITION is a move of 10% or more away from the last extreme, with the darker side below 0.80; a move
29
+ * further in the same direction extends the extreme instead of counting.
30
+ */
31
+ function markCellTransitions(frame, s) {
32
+ for (let c = 0; c < CELLS; c++) {
33
+ s.transition[c] = 0;
34
+ const l = Number(frame.luminances[c] ?? 0);
35
+ const ref = s.reference[c];
36
+ if (Number.isNaN(ref)) {
37
+ s.reference[c] = l;
38
+ continue;
39
+ }
40
+ const way = Math.sign(l - ref);
41
+ if (way === s.direction[c]) {
42
+ s.reference[c] = l;
43
+ continue;
44
+ }
45
+ if (Math.abs(l - ref) >= CHANGE && Math.min(l, ref) < DARK_BELOW) {
46
+ s.transition[c] = way;
47
+ s.direction[c] = way;
48
+ s.reference[c] = l;
49
+ }
50
+ }
51
+ }
52
+ /** A field makes a transition when 6 of its cells make one in the same direction in the same frame. */
53
+ function fieldTransition(transition, row, col) {
54
+ let wentUp = 0;
55
+ let wentDown = 0;
56
+ for (let dr = 0; dr < WINDOW_L; dr++) {
57
+ for (let dc = 0; dc < WINDOW_C; dc++) {
58
+ const way = transition[(row + dr) * COLUMNS + col + dc];
59
+ if (way > 0)
60
+ wentUp++;
61
+ else if (way < 0)
62
+ wentDown++;
63
+ }
64
+ }
65
+ return wentUp >= CELLS_FOR_AREA ? 1 : wentDown >= CELLS_FOR_AREA ? -1 : 0;
66
+ }
67
+ /** A FLASH is two opposing field transitions, and the pair then starts afresh. */
68
+ function pairFieldTransitions(t, s) {
69
+ let j = 0;
70
+ for (let row = 0; row + WINDOW_L <= ROWS; row++) {
71
+ for (let col = 0; col + WINDOW_C <= COLUMNS; col++, j++) {
72
+ const way = fieldTransition(s.transition, row, col);
73
+ if (!way)
74
+ continue;
75
+ if (s.openHalf[j] !== 0 && s.openHalf[j] !== way) {
76
+ s.flashTimes[j].push(t);
77
+ s.openHalf[j] = 0;
78
+ }
79
+ else {
80
+ s.openHalf[j] = way;
81
+ }
82
+ }
83
+ }
84
+ }
85
+ /** The most flashes any one field showed «within any one-second period». */
86
+ function worstSecond(flashTimes) {
87
+ let worst = 0;
88
+ for (const times of flashTimes) {
89
+ for (let i = 0, k = 0; i < times.length; i++) {
90
+ // less than a second apart; half a millisecond absorbs frame arithmetic
91
+ while (k < times.length && times[k] - times[i] < 1000 - 0.5)
92
+ k++;
93
+ worst = Math.max(worst, k - i);
94
+ }
95
+ }
96
+ return worst;
97
+ }
98
+ /** Counts general flashes per 10° field and returns the worst second. */
99
+ export function analyseFlashes(frames) {
100
+ const s = {
101
+ reference: new Float64Array(CELLS).fill(Number.NaN),
102
+ direction: new Int8Array(CELLS),
103
+ transition: new Int8Array(CELLS),
104
+ openHalf: new Int8Array(WINDOWS),
105
+ flashTimes: Array.from({ length: WINDOWS }, () => []),
106
+ };
107
+ for (const frame of frames) {
108
+ markCellTransitions(frame, s);
109
+ pairFieldTransitions(frame.t, s);
110
+ }
111
+ const worst = worstSecond(s.flashTimes);
112
+ return { passes: worst <= MAX_PER_SECOND, worstSecond: worst };
113
+ }
@@ -0,0 +1,11 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ /**
3
+ * THE GAME SPEED STEPS (ADR-0180): 100% down to 50% in steps of 10%, Celeste's Assist Mode, the example the Game Accessibility
4
+ * Guidelines cite for «Include an option to adjust the game speed» (Basic). One control slows timers, reaction windows and the
5
+ * world's pace at once.
6
+ */
7
+ export declare const GAME_SPEEDS: readonly number[];
8
+ /** A value outside the steps is not a speed: a stored typo lands on 100%, never on zero or on a speed nobody chose. */
9
+ export declare function isGameSpeed(v: number): number;
10
+ /** One press: the next step down, wrapping from 50% back to 100%. */
11
+ export declare function nextGameSpeed(v: number): number;
@@ -0,0 +1,16 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ /**
3
+ * THE GAME SPEED STEPS (ADR-0180): 100% down to 50% in steps of 10%, Celeste's Assist Mode, the example the Game Accessibility
4
+ * Guidelines cite for «Include an option to adjust the game speed» (Basic). One control slows timers, reaction windows and the
5
+ * world's pace at once.
6
+ */
7
+ export const GAME_SPEEDS = Object.freeze([1, 0.9, 0.8, 0.7, 0.6, 0.5]);
8
+ /** A value outside the steps is not a speed: a stored typo lands on 100%, never on zero or on a speed nobody chose. */
9
+ export function isGameSpeed(v) {
10
+ return GAME_SPEEDS.includes(v) ? v : 1;
11
+ }
12
+ /** One press: the next step down, wrapping from 50% back to 100%. */
13
+ export function nextGameSpeed(v) {
14
+ const i = GAME_SPEEDS.indexOf(isGameSpeed(v));
15
+ return GAME_SPEEDS[(i + 1) % GAME_SPEEDS.length];
16
+ }
@@ -0,0 +1,20 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ /**
3
+ * THE ENGINE'S GENRE LIST — the Dev's transcription of the Wikipedia list of video game genres (ADR-0156 §1).
4
+ *
5
+ * Optional (ADR-0153): a cartridge MAY declare one, and nobody assigns one to a game (§5). The transcription is the
6
+ * decision and the page only its source, so families and genres are written as the Dev wrote them. A family name is not a
7
+ * declarable genre, except MMO, which the list gives as both. Not in the list, and so not declarable: the by-purpose genres
8
+ * and sandbox / open world (§4).
9
+ */
10
+ export interface Genre {
11
+ readonly name: string;
12
+ readonly family: string;
13
+ /** Casino game is refused (§2); Horror game is to be avoided (§3). */
14
+ readonly mark?: 'refused' | 'avoid';
15
+ }
16
+ export declare const GENRES: readonly Genre[];
17
+ /** Is a declared genre acceptable? EMPTY means conformant; any line refuses the boot (a malformed declaration). */
18
+ export declare function genreProblems(genre: unknown): string[];
19
+ /** The line `problems` carries for an accepted genre with a mark: Horror game plays, and the author reads why to avoid it. */
20
+ export declare function genreWarning(genre: unknown): string | null;