@dreamboard-games/sdk 0.2.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 (369) hide show
  1. package/LICENSE.md +96 -0
  2. package/README.md +12 -0
  3. package/dist/HandView-ncJIVLhN.d.ts +193 -0
  4. package/dist/ResourceCounter-CTREyF73.d.ts +102 -0
  5. package/dist/ThemeProvider-fy0_QzgO.d.ts +99 -0
  6. package/dist/bundle-TIZcw8LB.d.ts +281 -0
  7. package/dist/cards-Sl3b40Mv.d.ts +13 -0
  8. package/dist/chunk-7YAHLYBR.js +481 -0
  9. package/dist/chunk-7YAHLYBR.js.map +1 -0
  10. package/dist/chunk-FDNZTDD6.js +8085 -0
  11. package/dist/chunk-FDNZTDD6.js.map +1 -0
  12. package/dist/chunk-GKKBPPSW.js +598 -0
  13. package/dist/chunk-GKKBPPSW.js.map +1 -0
  14. package/dist/chunk-I46YJSOD.js +1 -0
  15. package/dist/chunk-I46YJSOD.js.map +1 -0
  16. package/dist/chunk-KAELH4KC.js +104 -0
  17. package/dist/chunk-KAELH4KC.js.map +1 -0
  18. package/dist/chunk-PZ5AY32C.js +10 -0
  19. package/dist/chunk-PZ5AY32C.js.map +1 -0
  20. package/dist/chunk-T3ZKNUZ7.js +1 -0
  21. package/dist/chunk-T3ZKNUZ7.js.map +1 -0
  22. package/dist/chunk-T52J5RMF.js +1 -0
  23. package/dist/chunk-T52J5RMF.js.map +1 -0
  24. package/dist/chunk-TDSWKVZ4.js +5401 -0
  25. package/dist/chunk-TDSWKVZ4.js.map +1 -0
  26. package/dist/chunk-U5C6BONG.js +34 -0
  27. package/dist/chunk-U5C6BONG.js.map +1 -0
  28. package/dist/chunk-VDXOF4FW.js +69 -0
  29. package/dist/chunk-VDXOF4FW.js.map +1 -0
  30. package/dist/chunk-VFTAA4WO.js +115 -0
  31. package/dist/chunk-VFTAA4WO.js.map +1 -0
  32. package/dist/chunk-WN74KVNY.js +17 -0
  33. package/dist/chunk-WN74KVNY.js.map +1 -0
  34. package/dist/chunk-WYPQ3GG5.js +10990 -0
  35. package/dist/chunk-WYPQ3GG5.js.map +1 -0
  36. package/dist/components-D5ZRE2Hl.d.ts +1451 -0
  37. package/dist/generated/runtime/primitives.d.ts +12 -0
  38. package/dist/generated/runtime/primitives.js +180 -0
  39. package/dist/generated/runtime/primitives.js.map +1 -0
  40. package/dist/generated/runtime-api.d.ts +3 -0
  41. package/dist/generated/runtime-api.js +2 -0
  42. package/dist/generated/runtime-api.js.map +1 -0
  43. package/dist/generated/runtime.d.ts +14 -0
  44. package/dist/generated/runtime.js +18 -0
  45. package/dist/generated/runtime.js.map +1 -0
  46. package/dist/generated/workspace-contract.d.ts +14 -0
  47. package/dist/generated/workspace-contract.js +14 -0
  48. package/dist/generated/workspace-contract.js.map +1 -0
  49. package/dist/hex-board-view-D_07hO6O.d.ts +933 -0
  50. package/dist/hex-color-MhOyuY-o.d.ts +8 -0
  51. package/dist/index-BwqPQtBu.d.ts +1433 -0
  52. package/dist/index.d.ts +1 -0
  53. package/dist/index.js +12 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/infrastructure/reducer-bundle-abi.d.ts +1083 -0
  56. package/dist/infrastructure/reducer-bundle-abi.js +14 -0
  57. package/dist/infrastructure/reducer-bundle-abi.js.map +1 -0
  58. package/dist/infrastructure/workspace-codegen.d.ts +53 -0
  59. package/dist/infrastructure/workspace-codegen.js +44 -0
  60. package/dist/infrastructure/workspace-codegen.js.map +1 -0
  61. package/dist/manifest-contract-BNHVGFtU.d.ts +9 -0
  62. package/dist/package-set.d.ts +13 -0
  63. package/dist/package-set.js +12 -0
  64. package/dist/package-set.js.map +1 -0
  65. package/dist/primitive-props-DpKs-GCr.d.ts +11 -0
  66. package/dist/reducer.d.ts +3786 -0
  67. package/dist/reducer.js +8131 -0
  68. package/dist/reducer.js.map +1 -0
  69. package/dist/runtime/primitives.d.ts +226 -0
  70. package/dist/runtime/primitives.js +180 -0
  71. package/dist/runtime/primitives.js.map +1 -0
  72. package/dist/runtime/types/runtime-api.d.ts +1 -0
  73. package/dist/runtime/types/runtime-api.js +2 -0
  74. package/dist/runtime/types/runtime-api.js.map +1 -0
  75. package/dist/runtime/workspace-contract.d.ts +172 -0
  76. package/dist/runtime/workspace-contract.js +14 -0
  77. package/dist/runtime/workspace-contract.js.map +1 -0
  78. package/dist/runtime-api-3dshj6kK.d.ts +101 -0
  79. package/dist/runtime-api-DWxvTr-O.d.ts +379 -0
  80. package/dist/runtime.d.ts +58 -0
  81. package/dist/runtime.js +13 -0
  82. package/dist/runtime.js.map +1 -0
  83. package/dist/slots-1GPGihk8.d.ts +8 -0
  84. package/dist/testing.d.ts +149 -0
  85. package/dist/testing.js +513 -0
  86. package/dist/testing.js.map +1 -0
  87. package/dist/types.d.ts +496 -0
  88. package/dist/types.js +28 -0
  89. package/dist/types.js.map +1 -0
  90. package/dist/ui/components.d.ts +16 -0
  91. package/dist/ui/components.js +192 -0
  92. package/dist/ui/components.js.map +1 -0
  93. package/dist/ui/defaults.d.ts +19 -0
  94. package/dist/ui/defaults.js +104 -0
  95. package/dist/ui/defaults.js.map +1 -0
  96. package/dist/ui/plugin-styles.css +250 -0
  97. package/dist/ui/types/player-state.d.ts +365 -0
  98. package/dist/ui/types/player-state.js +1 -0
  99. package/dist/ui/types/player-state.js.map +1 -0
  100. package/dist/ui-contract-iQfTtUSL.d.ts +1161 -0
  101. package/dist/ui.d.ts +320 -0
  102. package/dist/ui.js +253 -0
  103. package/dist/ui.js.map +1 -0
  104. package/package.json +199 -0
  105. package/src/generated/reducer-contract/builders.ts +90 -0
  106. package/src/generated/reducer-contract/version.ts +9 -0
  107. package/src/generated/reducer-contract/wire.ts +100 -0
  108. package/src/generated/reducer-contract/zod.ts +101 -0
  109. package/src/generated/runtime/primitives.ts +2 -0
  110. package/src/generated/runtime-api.ts +5 -0
  111. package/src/generated/runtime.ts +35 -0
  112. package/src/generated/workspace-contract.ts +2 -0
  113. package/src/index.ts +7 -0
  114. package/src/infrastructure/reducer-bundle-abi.ts +8 -0
  115. package/src/infrastructure/reducer-contract/bundle.ts +37 -0
  116. package/src/infrastructure/workspace-codegen/hex-geometry.ts +69 -0
  117. package/src/infrastructure/workspace-codegen/index.ts +64 -0
  118. package/src/infrastructure/workspace-codegen/manifest-contract.ts +6632 -0
  119. package/src/infrastructure/workspace-codegen/manifest-validation.ts +795 -0
  120. package/src/infrastructure/workspace-codegen/ownership.ts +131 -0
  121. package/src/infrastructure/workspace-codegen/preset-card-sets.ts +169 -0
  122. package/src/infrastructure/workspace-codegen/seeds.ts +1705 -0
  123. package/src/infrastructure/workspace-codegen.ts +1 -0
  124. package/src/package-set.ts +19 -0
  125. package/src/reducer/authoring/contract.ts +157 -0
  126. package/src/reducer/authoring/effect.ts +224 -0
  127. package/src/reducer/authoring/game.ts +23 -0
  128. package/src/reducer/authoring/interaction.ts +98 -0
  129. package/src/reducer/authoring/phase.ts +300 -0
  130. package/src/reducer/authoring/types.ts +70 -0
  131. package/src/reducer/authoring/validation.ts +382 -0
  132. package/src/reducer/authoring/view-stage.ts +68 -0
  133. package/src/reducer/authoring.ts +29 -0
  134. package/src/reducer/bundle/ingress-bundle.ts +491 -0
  135. package/src/reducer/bundle/trusted/engine-instruction-resolver.ts +254 -0
  136. package/src/reducer/bundle/trusted/flow-instruction-resolver.ts +73 -0
  137. package/src/reducer/bundle/trusted/instruction-runner.ts +414 -0
  138. package/src/reducer/bundle/trusted/interaction-authorization.ts +137 -0
  139. package/src/reducer/bundle/trusted/interaction-collectors.ts +859 -0
  140. package/src/reducer/bundle/trusted/interaction-decision.ts +747 -0
  141. package/src/reducer/bundle/trusted/interaction-resolver.ts +95 -0
  142. package/src/reducer/bundle/trusted/interaction-types.ts +171 -0
  143. package/src/reducer/bundle/trusted/lifecycle-runner.ts +427 -0
  144. package/src/reducer/bundle/trusted/projection-builder.ts +356 -0
  145. package/src/reducer/bundle/trusted/projection-context.ts +39 -0
  146. package/src/reducer/bundle/trusted/rng-sampler.ts +150 -0
  147. package/src/reducer/bundle/trusted/runtime-registry.ts +120 -0
  148. package/src/reducer/bundle/trusted/runtime-scope.ts +336 -0
  149. package/src/reducer/bundle/trusted/simultaneous-player.ts +97 -0
  150. package/src/reducer/bundle/trusted/stage-resolver.ts +87 -0
  151. package/src/reducer/bundle/trusted/static-projection.ts +116 -0
  152. package/src/reducer/bundle/trusted/trusted-runtime-args.ts +97 -0
  153. package/src/reducer/bundle/trusted/trusted-runtime-result.ts +39 -0
  154. package/src/reducer/bundle/trusted/trusted-setup-profiles.ts +43 -0
  155. package/src/reducer/bundle/trusted/trusted-state-codec.ts +48 -0
  156. package/src/reducer/bundle/trusted-bundle.ts +97 -0
  157. package/src/reducer/bundle/types.ts +171 -0
  158. package/src/reducer/bundle.ts +2 -0
  159. package/src/reducer/client-param-schemas.ts +57 -0
  160. package/src/reducer/compose.ts +34 -0
  161. package/src/reducer/core/runtime-input.ts +30 -0
  162. package/src/reducer/core/runtime-instruction.ts +59 -0
  163. package/src/reducer/core/types.ts +62 -0
  164. package/src/reducer/definition-index.ts +277 -0
  165. package/src/reducer/derived.ts +106 -0
  166. package/src/reducer/effects.ts +92 -0
  167. package/src/reducer/engine/runtime-instruction-engine.ts +155 -0
  168. package/src/reducer/ingress/decode-runtime-input.ts +7 -0
  169. package/src/reducer/ingress/decode-session-state.ts +9 -0
  170. package/src/reducer/ingress/encode-session-state.ts +6 -0
  171. package/src/reducer/ingress/input-codec.ts +18 -0
  172. package/src/reducer/ingress/phase-schemas.ts +62 -0
  173. package/src/reducer/ingress/raw-types.ts +107 -0
  174. package/src/reducer/ingress/runtime-codec.ts +14 -0
  175. package/src/reducer/ingress/runtime-payload.ts +13 -0
  176. package/src/reducer/ingress/session-codec.ts +392 -0
  177. package/src/reducer/ingress/types.ts +6 -0
  178. package/src/reducer/inputs/boardInput.ts +217 -0
  179. package/src/reducer/inputs/boardTarget.ts +190 -0
  180. package/src/reducer/inputs/cardInput.ts +86 -0
  181. package/src/reducer/inputs/cardTarget.ts +101 -0
  182. package/src/reducer/inputs/choiceTarget.ts +104 -0
  183. package/src/reducer/inputs/defineInputs.ts +71 -0
  184. package/src/reducer/inputs/formInput.ts +809 -0
  185. package/src/reducer/inputs/many.ts +120 -0
  186. package/src/reducer/inputs/promptInput.ts +87 -0
  187. package/src/reducer/inputs/rngInput.ts +58 -0
  188. package/src/reducer/inputs/targetRule.ts +123 -0
  189. package/src/reducer/inputs.ts +41 -0
  190. package/src/reducer/model/definition.ts +1072 -0
  191. package/src/reducer/model/extract.ts +745 -0
  192. package/src/reducer/model/manifest.ts +570 -0
  193. package/src/reducer/model/queries.ts +641 -0
  194. package/src/reducer/model/runtime.ts +264 -0
  195. package/src/reducer/model/spec.ts +1386 -0
  196. package/src/reducer/model/table.ts +260 -0
  197. package/src/reducer/model.ts +7 -0
  198. package/src/reducer/ops.ts +1034 -0
  199. package/src/reducer/parse-utils.ts +28 -0
  200. package/src/reducer/per-player.ts +422 -0
  201. package/src/reducer/rng.ts +69 -0
  202. package/src/reducer/schema-helpers.ts +185 -0
  203. package/src/reducer/setup-bootstrap-helpers.ts +171 -0
  204. package/src/reducer/setup-bootstrap.ts +481 -0
  205. package/src/reducer/table-ops.ts +2671 -0
  206. package/src/reducer/table-queries.ts +372 -0
  207. package/src/reducer/transaction.ts +120 -0
  208. package/src/reducer.ts +314 -0
  209. package/src/runtime/primitives.ts +1 -0
  210. package/src/runtime/types/runtime-api.ts +1 -0
  211. package/src/runtime/workspace-contract.ts +32 -0
  212. package/src/runtime-internal/components/InteractionForm.tsx +1309 -0
  213. package/src/runtime-internal/components/PluginRuntime.tsx +103 -0
  214. package/src/runtime-internal/components/board/target-layer.ts +70 -0
  215. package/src/runtime-internal/context/ClientParamSchemaContext.tsx +44 -0
  216. package/src/runtime-internal/context/InteractionDraftContext.tsx +279 -0
  217. package/src/runtime-internal/context/PluginSessionContext.tsx +47 -0
  218. package/src/runtime-internal/context/PluginStateContext.tsx +262 -0
  219. package/src/runtime-internal/context/RuntimeContext.tsx +96 -0
  220. package/src/runtime-internal/defaults/components.tsx +409 -0
  221. package/src/runtime-internal/defaults/index.ts +11 -0
  222. package/src/runtime-internal/errors/ValidationError.ts +29 -0
  223. package/src/runtime-internal/hooks/useActivePlayers.ts +33 -0
  224. package/src/runtime-internal/hooks/useBoardInteractions.ts +665 -0
  225. package/src/runtime-internal/hooks/useGameSelector.ts +105 -0
  226. package/src/runtime-internal/hooks/useGameView.ts +9 -0
  227. package/src/runtime-internal/hooks/useInteractionByKey.ts +354 -0
  228. package/src/runtime-internal/hooks/useInteractionHandle.ts +438 -0
  229. package/src/runtime-internal/hooks/useIsMyTurn.ts +20 -0
  230. package/src/runtime-internal/hooks/useLobby.ts +76 -0
  231. package/src/runtime-internal/hooks/useMe.ts +48 -0
  232. package/src/runtime-internal/hooks/usePlayerInfo.ts +28 -0
  233. package/src/runtime-internal/hooks/usePlayerTurnOrder.ts +23 -0
  234. package/src/runtime-internal/hooks/usePluginRuntime.ts +147 -0
  235. package/src/runtime-internal/hooks/useSeatInbox.ts +61 -0
  236. package/src/runtime-internal/hooks/useSimultaneousPhase.ts +10 -0
  237. package/src/runtime-internal/index.ts +42 -0
  238. package/src/runtime-internal/internal.ts +43 -0
  239. package/src/runtime-internal/plugin-styles.css +250 -0
  240. package/src/runtime-internal/primitives/board.tsx +459 -0
  241. package/src/runtime-internal/primitives/dialog-lifecycle.ts +58 -0
  242. package/src/runtime-internal/primitives/dice.tsx +79 -0
  243. package/src/runtime-internal/primitives/game-ui-provider.tsx +35 -0
  244. package/src/runtime-internal/primitives/game.tsx +387 -0
  245. package/src/runtime-internal/primitives/hand-intent-adapter.ts +147 -0
  246. package/src/runtime-internal/primitives/hand-surface.tsx +594 -0
  247. package/src/runtime-internal/primitives/index.ts +196 -0
  248. package/src/runtime-internal/primitives/interaction-form-binding.tsx +56 -0
  249. package/src/runtime-internal/primitives/interaction-submit.ts +90 -0
  250. package/src/runtime-internal/primitives/interaction.tsx +987 -0
  251. package/src/runtime-internal/primitives/phase.tsx +43 -0
  252. package/src/runtime-internal/primitives/player-roster.tsx +302 -0
  253. package/src/runtime-internal/primitives/primitive-props.tsx +101 -0
  254. package/src/runtime-internal/primitives/prompt.tsx +255 -0
  255. package/src/runtime-internal/primitives/ui.tsx +60 -0
  256. package/src/runtime-internal/primitives/zone.tsx +791 -0
  257. package/src/runtime-internal/reducer.ts +30 -0
  258. package/src/runtime-internal/runtime/createPluginRuntimeAPI.ts +605 -0
  259. package/src/runtime-internal/types/plugin-state.ts +508 -0
  260. package/src/runtime-internal/types/reducer-state.ts +24 -0
  261. package/src/runtime-internal/types/runtime-api.ts +114 -0
  262. package/src/runtime-internal/ui-contract.ts +519 -0
  263. package/src/runtime-internal/utils/card-intent-adapter.ts +546 -0
  264. package/src/runtime-internal/utils/interaction-inputs.ts +492 -0
  265. package/src/runtime-internal/utils/interaction-labels.ts +23 -0
  266. package/src/runtime-internal/utils/interaction-router.ts +273 -0
  267. package/src/runtime-internal/utils/interaction-status.ts +74 -0
  268. package/src/runtime-internal/workspace-contract.ts +1170 -0
  269. package/src/runtime.ts +34 -0
  270. package/src/testing/create-expect-api.ts +352 -0
  271. package/src/testing/create-test-runtime.ts +381 -0
  272. package/src/testing/definitions.ts +127 -0
  273. package/src/testing/index.ts +3 -0
  274. package/src/testing.ts +1 -0
  275. package/src/type-stubs/manifest-contract.d.ts +42 -0
  276. package/src/type-stubs/manifest-contract.js +72 -0
  277. package/src/type-stubs/ui-contract.d.ts +5 -0
  278. package/src/type-stubs/ui-contract.js +1 -0
  279. package/src/types/authoring-card-properties.type-test.ts +266 -0
  280. package/src/types/authoring.ts +1282 -0
  281. package/src/types/cards.ts +19 -0
  282. package/src/types/contracts.ts +1550 -0
  283. package/src/types/generated-helpers.ts +35 -0
  284. package/src/types/index.ts +147 -0
  285. package/src/types/slots.ts +11 -0
  286. package/src/types.ts +1 -0
  287. package/src/ui/components/ActionButton.tsx +97 -0
  288. package/src/ui/components/ActionPanel.tsx +315 -0
  289. package/src/ui/components/Card.tsx +378 -0
  290. package/src/ui/components/CardDragSurface.tsx +1076 -0
  291. package/src/ui/components/ChromeSuppressionContext.tsx +70 -0
  292. package/src/ui/components/CostDisplay.tsx +145 -0
  293. package/src/ui/components/DiceRoller.tsx +581 -0
  294. package/src/ui/components/Drawer.tsx +180 -0
  295. package/src/ui/components/ErrorBoundary.tsx +275 -0
  296. package/src/ui/components/GameEndDisplay.tsx +398 -0
  297. package/src/ui/components/GameSkeleton.tsx +260 -0
  298. package/src/ui/components/Hand.tsx +468 -0
  299. package/src/ui/components/HandDock.tsx +299 -0
  300. package/src/ui/components/HandView.tsx +441 -0
  301. package/src/ui/components/MobileHandTray.tsx +381 -0
  302. package/src/ui/components/MoreActions.tsx +143 -0
  303. package/src/ui/components/PhaseIndicator.tsx +341 -0
  304. package/src/ui/components/PlayArea.tsx +146 -0
  305. package/src/ui/components/PrimaryActionButton.tsx +336 -0
  306. package/src/ui/components/PrimaryButton.tsx +45 -0
  307. package/src/ui/components/ResourceCounter.tsx +270 -0
  308. package/src/ui/components/StagingZone.tsx +134 -0
  309. package/src/ui/components/ThemedButton.tsx +113 -0
  310. package/src/ui/components/Toast.tsx +264 -0
  311. package/src/ui/components/board/HexGrid.tsx +1294 -0
  312. package/src/ui/components/board/NetworkGraph.tsx +476 -0
  313. package/src/ui/components/board/SlotSystem.tsx +388 -0
  314. package/src/ui/components/board/SquareGrid.tsx +1165 -0
  315. package/src/ui/components/board/TrackBoard.tsx +496 -0
  316. package/src/ui/components/board/ZoneMap.tsx +448 -0
  317. package/src/ui/components/board/hex-board-view.ts +123 -0
  318. package/src/ui/components/board/index.ts +142 -0
  319. package/src/ui/components/board/interaction-accessibility.ts +21 -0
  320. package/src/ui/components/board/target-layer.ts +66 -0
  321. package/src/ui/components/card-render-content.type-test.ts +27 -0
  322. package/src/ui/components/hand-layout-math.ts +163 -0
  323. package/src/ui/components/hand-pointer-engine.ts +413 -0
  324. package/src/ui/components/index.ts +245 -0
  325. package/src/ui/components.ts +1 -0
  326. package/src/ui/defaults/components.tsx +106 -0
  327. package/src/ui/defaults/index.ts +8 -0
  328. package/src/ui/defaults.ts +1 -0
  329. package/src/ui/errors/ValidationError.ts +29 -0
  330. package/src/ui/helpers/cards.ts +19 -0
  331. package/src/ui/helpers/track-board.ts +211 -0
  332. package/src/ui/hooks/useBoardTopology.ts +316 -0
  333. package/src/ui/hooks/useCards.ts +10 -0
  334. package/src/ui/hooks/useHandCardPointer.ts +381 -0
  335. package/src/ui/hooks/useHandLayout.ts +378 -0
  336. package/src/ui/hooks/useHandPresentation.ts +121 -0
  337. package/src/ui/hooks/useHexBoard.ts +74 -0
  338. package/src/ui/hooks/useHexGrid.ts +185 -0
  339. package/src/ui/hooks/useIsMobile.ts +35 -0
  340. package/src/ui/hooks/usePanZoom.ts +278 -0
  341. package/src/ui/hooks/useSquareBoard.ts +124 -0
  342. package/src/ui/hooks/useSquareGrid.ts +328 -0
  343. package/src/ui/index.ts +98 -0
  344. package/src/ui/internal/ui/alert.tsx +51 -0
  345. package/src/ui/internal/ui/button.tsx +58 -0
  346. package/src/ui/internal/ui/dialog.tsx +134 -0
  347. package/src/ui/internal/ui/input.tsx +21 -0
  348. package/src/ui/internal/ui/label.tsx +21 -0
  349. package/src/ui/internal/ui/select.tsx +129 -0
  350. package/src/ui/internal/ui/tooltip.tsx +54 -0
  351. package/src/ui/internal/ui/utils.ts +5 -0
  352. package/src/ui/plugin-styles.css +250 -0
  353. package/src/ui/primitives/dialog-lifecycle.ts +58 -0
  354. package/src/ui/primitives/dice.tsx +79 -0
  355. package/src/ui/primitives/primitive-props.tsx +101 -0
  356. package/src/ui/theme/ThemeProvider.tsx +252 -0
  357. package/src/ui/theme/board.ts +61 -0
  358. package/src/ui/theme/css-vars.ts +105 -0
  359. package/src/ui/theme/derive.ts +240 -0
  360. package/src/ui/theme/index.ts +61 -0
  361. package/src/ui/theme/presets/arcade.ts +261 -0
  362. package/src/ui/theme/presets/studio.ts +261 -0
  363. package/src/ui/theme/presets/tabletop.ts +266 -0
  364. package/src/ui/theme/tokens.ts +392 -0
  365. package/src/ui/types/hex-color.ts +20 -0
  366. package/src/ui/types/player-state.ts +463 -0
  367. package/src/ui/types/tiled-board.ts +785 -0
  368. package/src/ui/types/visual-state.ts +137 -0
  369. package/src/ui.ts +1 -0
@@ -0,0 +1,95 @@
1
+ import type {
2
+ PhaseMapOf,
3
+ ReducerGameContractLike,
4
+ ReducerReject,
5
+ ReducerValidationResult,
6
+ ViewMapOf,
7
+ } from "../../model";
8
+ import {
9
+ collectEligibleTargets,
10
+ collectFirstCardZoneId,
11
+ findCardInputKey,
12
+ findCardInputKeyForZone,
13
+ parseInteractionParams,
14
+ } from "./interaction-collectors";
15
+ import { createInteractionAuthorization } from "./interaction-authorization";
16
+ import { createInteractionDecisionResolver } from "./interaction-decision";
17
+ import { createStageResolver } from "./stage-resolver";
18
+ import {
19
+ rejectResult,
20
+ type TrustedInput,
21
+ type TrustedPlayerId,
22
+ type TrustedRuntimeScope,
23
+ type TrustedState,
24
+ } from "./runtime-scope";
25
+
26
+ export type { InteractionDescriptorShape } from "./interaction-types";
27
+
28
+ export function createInteractionResolver<
29
+ Contract extends ReducerGameContractLike,
30
+ Definitions extends PhaseMapOf<Contract>,
31
+ Views extends ViewMapOf<Contract>,
32
+ >(scope: TrustedRuntimeScope<Contract, Definitions, Views>) {
33
+ type State = TrustedState<Contract>;
34
+ type PlayerId = TrustedPlayerId<Contract>;
35
+ type ReducerInput = TrustedInput<Contract>;
36
+
37
+ const stages = createStageResolver(scope);
38
+ const authorization = createInteractionAuthorization(scope);
39
+ const decisions = createInteractionDecisionResolver(
40
+ scope,
41
+ stages,
42
+ authorization,
43
+ );
44
+
45
+ function validateClientInput(
46
+ state: State,
47
+ input: ReducerInput,
48
+ ): ReducerValidationResult {
49
+ if (input.kind === "interaction") {
50
+ const decision = decisions.resolveInteractionDecision({
51
+ state,
52
+ playerId: input.playerId as PlayerId,
53
+ interactionId: input.interactionId,
54
+ params: (input.params ?? {}) as Record<string, unknown>,
55
+ mode: "submit",
56
+ });
57
+ return decision.validation;
58
+ }
59
+ return { valid: true };
60
+ }
61
+
62
+ function validateOrReject(
63
+ state: State,
64
+ input: ReducerInput,
65
+ ): ReducerReject | null {
66
+ const validation = validateClientInput(state, input);
67
+ if (validation.valid) {
68
+ return null;
69
+ }
70
+ const invalidValidation = validation as Exclude<
71
+ ReducerValidationResult,
72
+ { valid: true }
73
+ >;
74
+ return rejectResult(invalidValidation.errorCode, invalidValidation.message);
75
+ }
76
+
77
+ return {
78
+ collectEligibleTargets,
79
+ collectFirstCardZoneId,
80
+ evaluateInteractionCost: decisions.evaluateInteractionCost,
81
+ findCardInputKey,
82
+ findCardInputKeyForZone,
83
+ isActorAuthorized: authorization.isActorAuthorized,
84
+ isInteractionAllowedInStep: stages.isInteractionAllowedInStep,
85
+ parseInteractionParams,
86
+ resolveActiveStage: stages.resolveActiveStage,
87
+ resolveActiveStageAllowlist: stages.resolveActiveStageAllowlist,
88
+ resolveAvailableInteractionsFor: decisions.resolveAvailableInteractionsFor,
89
+ resolveInteractionActorAuthorization:
90
+ authorization.resolveInteractionActorAuthorization,
91
+ resolveInteractionDecision: decisions.resolveInteractionDecision,
92
+ validateClientInput,
93
+ validateOrReject,
94
+ };
95
+ }
@@ -0,0 +1,171 @@
1
+ import type {
2
+ AnyInteractionSpec,
3
+ InputCollectorKind,
4
+ InputDomainDescriptor,
5
+ InteractionIdOfDefinition,
6
+ InteractionKind,
7
+ PhaseMapOf,
8
+ ReducerGameContractLike,
9
+ ReducerValidationResult,
10
+ ViewMapOf,
11
+ } from "../../model";
12
+ import type {
13
+ TrustedDefinition,
14
+ TrustedDomainState,
15
+ TrustedManifest,
16
+ TrustedPhaseName,
17
+ TrustedPlayerId,
18
+ TrustedState,
19
+ } from "./runtime-scope";
20
+ import type { ProjectionContext } from "./projection-context";
21
+
22
+ export type TrustedInteractionId<
23
+ Contract extends ReducerGameContractLike,
24
+ Definitions extends PhaseMapOf<Contract>,
25
+ Views extends ViewMapOf<Contract>,
26
+ > = InteractionIdOfDefinition<TrustedDefinition<Contract, Definitions, Views>>;
27
+
28
+ export type InteractionDescriptorContext<PlayerId extends string = string> = {
29
+ to: PlayerId;
30
+ title?: string;
31
+ options?: Array<{ id: string; label?: string }>;
32
+ };
33
+
34
+ export type InteractionCommitPolicyShape =
35
+ | { mode: "manual" }
36
+ | { mode: "autoWhenReady" };
37
+
38
+ export type InteractionAvailabilityShape =
39
+ | { status: "available" }
40
+ | { status: "notYourTurn"; reason: string }
41
+ | {
42
+ status: "insufficientResources";
43
+ reason: string;
44
+ missingResources: Record<string, number>;
45
+ }
46
+ | { status: "blocked"; reason: string; code?: string };
47
+
48
+ type InteractionDescriptorBaseShape<
49
+ PhaseName extends string = string,
50
+ InteractionId extends string = string,
51
+ ZoneId extends string = string,
52
+ > = {
53
+ phaseName: PhaseName;
54
+ interactionKey: `${PhaseName}.${InteractionId}`;
55
+ interactionId: InteractionId;
56
+ commit: InteractionCommitPolicyShape;
57
+ zoneId?: ZoneId;
58
+ zoneIds?: readonly ZoneId[];
59
+ inputs: InteractionInputDescriptorShape[];
60
+ cost?: Record<string, number>;
61
+ currentResources?: Record<string, number>;
62
+ availability: InteractionAvailabilityShape;
63
+ };
64
+
65
+ export type ActionInteractionDescriptorShape<
66
+ PhaseName extends string = string,
67
+ InteractionId extends string = string,
68
+ ZoneId extends string = string,
69
+ > = InteractionDescriptorBaseShape<PhaseName, InteractionId, ZoneId> & {
70
+ kind: "action";
71
+ };
72
+
73
+ export type PromptInteractionDescriptorShape<
74
+ PhaseName extends string = string,
75
+ InteractionId extends string = string,
76
+ PlayerId extends string = string,
77
+ ZoneId extends string = string,
78
+ > = InteractionDescriptorBaseShape<PhaseName, InteractionId, ZoneId> & {
79
+ kind: "prompt";
80
+ context: InteractionDescriptorContext<PlayerId>;
81
+ };
82
+
83
+ export type InteractionDescriptorShape<
84
+ PhaseName extends string = string,
85
+ InteractionId extends string = string,
86
+ PlayerId extends string = string,
87
+ ZoneId extends string = string,
88
+ > =
89
+ | ActionInteractionDescriptorShape<PhaseName, InteractionId, ZoneId>
90
+ | PromptInteractionDescriptorShape<
91
+ PhaseName,
92
+ InteractionId,
93
+ PlayerId,
94
+ ZoneId
95
+ >;
96
+
97
+ export type TrustedInteractionDescriptorShape<
98
+ Contract extends ReducerGameContractLike,
99
+ Definitions extends PhaseMapOf<Contract>,
100
+ Views extends ViewMapOf<Contract>,
101
+ > = InteractionDescriptorShape<
102
+ TrustedPhaseName<Contract, Definitions, Views>,
103
+ TrustedInteractionId<Contract, Definitions, Views>,
104
+ TrustedPlayerId<Contract>
105
+ >;
106
+
107
+ export type InteractionInputDescriptorShape = {
108
+ key: string;
109
+ kind: InputCollectorKind;
110
+ domain: InputDomainDescriptor;
111
+ defaultValue?: unknown;
112
+ };
113
+
114
+ export type InteractionActorAuthorization<PlayerId extends string> =
115
+ | { readonly mode: "addressees"; readonly addressees: ReadonlySet<PlayerId> }
116
+ | { readonly mode: "actors"; readonly actors: ReadonlySet<PlayerId> }
117
+ | { readonly mode: "active" };
118
+
119
+ export type ResolveDecisionMode = "descriptor" | "card" | "submit";
120
+
121
+ export type ResolveDecisionInput<
122
+ Contract extends ReducerGameContractLike,
123
+ Definitions extends PhaseMapOf<Contract>,
124
+ Views extends ViewMapOf<Contract>,
125
+ > = {
126
+ state: TrustedState<Contract>;
127
+ playerId: TrustedPlayerId<Contract>;
128
+ interactionId: string;
129
+ params?: Record<string, unknown>;
130
+ mode: ResolveDecisionMode;
131
+ projection?: ProjectionContext<
132
+ TrustedDomainState<Contract>,
133
+ TrustedState<Contract>
134
+ >;
135
+ };
136
+
137
+ export type InteractionDecisionResult<
138
+ Contract extends ReducerGameContractLike,
139
+ Definitions extends PhaseMapOf<Contract>,
140
+ Views extends ViewMapOf<Contract>,
141
+ > =
142
+ | {
143
+ found: false;
144
+ validation: ReducerValidationResult;
145
+ }
146
+ | {
147
+ found: true;
148
+ interaction: AnyInteractionSpec<
149
+ TrustedDomainState<Contract>,
150
+ TrustedManifest<Contract>
151
+ >;
152
+ parsedParams: Record<string, unknown>;
153
+ visible: boolean;
154
+ descriptor: TrustedInteractionDescriptorShape<
155
+ Contract,
156
+ Definitions,
157
+ Views
158
+ >;
159
+ validation: ReducerValidationResult;
160
+ };
161
+
162
+ export function makeValidationError(
163
+ errorCode: string,
164
+ message?: string,
165
+ ): ReducerValidationResult {
166
+ return {
167
+ valid: false,
168
+ errorCode,
169
+ message,
170
+ };
171
+ }
@@ -0,0 +1,427 @@
1
+ import { safeParseOrThrow } from "../../parse-utils";
2
+ import { applySetupBootstrap } from "../../setup-bootstrap";
3
+ import { createStateQueries } from "../../table-queries";
4
+ import type {
5
+ ExactManifestContractOf,
6
+ PhaseMapOf,
7
+ ReducerGameContractLike,
8
+ RuntimeSetupSelection,
9
+ RuntimeSetupSelectionInput,
10
+ ViewMapOf,
11
+ } from "../../model";
12
+ import type { RuntimeInstructionForState } from "../../core/runtime-instruction";
13
+ import { isPerPlayer } from "../../per-player";
14
+ import { normalizeResult } from "./runtime-scope";
15
+ import { createMutableRandomHelpers } from "./rng-sampler";
16
+ import type { createInteractionResolver } from "./interaction-resolver";
17
+ import type {
18
+ TrustedDomainState,
19
+ TrustedManifest,
20
+ TrustedPhaseName,
21
+ TrustedPlayerId,
22
+ TrustedRuntimeScope,
23
+ TrustedSessionState,
24
+ TrustedState,
25
+ } from "./runtime-scope";
26
+
27
+ type InteractionResolverFor<
28
+ Contract extends ReducerGameContractLike,
29
+ Definitions extends PhaseMapOf<Contract>,
30
+ Views extends ViewMapOf<Contract>,
31
+ > = ReturnType<typeof createInteractionResolver<Contract, Definitions, Views>>;
32
+
33
+ export function createLifecycleRunner<
34
+ Contract extends ReducerGameContractLike,
35
+ Definitions extends PhaseMapOf<Contract>,
36
+ Views extends ViewMapOf<Contract>,
37
+ >(
38
+ scope: TrustedRuntimeScope<Contract, Definitions, Views>,
39
+ interactions: InteractionResolverFor<Contract, Definitions, Views>,
40
+ ) {
41
+ type DomainState = TrustedDomainState<Contract>;
42
+ type SessionState = TrustedSessionState<Contract>;
43
+ type State = TrustedState<Contract>;
44
+ type Manifest = TrustedManifest<Contract>;
45
+ type ExactManifest = ExactManifestContractOf<Contract>;
46
+ type PhaseName = TrustedPhaseName<Contract, Definitions, Views>;
47
+ type PlayerId = TrustedPlayerId<Contract>;
48
+
49
+ function resolveSelectedSetup(
50
+ setup: RuntimeSetupSelectionInput<Manifest> | null | undefined,
51
+ ): State["runtime"]["setup"] {
52
+ if (!setup) {
53
+ return null;
54
+ }
55
+ const manifestProfile = scope.manifestSetupProfilesById[setup.profileId];
56
+ if (!manifestProfile) {
57
+ throw new Error(`Unknown setup profile '${setup.profileId}'.`);
58
+ }
59
+ const resolvedOptionValues: Record<string, string | null> =
60
+ Object.fromEntries(
61
+ scope.definition.contract.manifest.literals.setupOptionIds.map(
62
+ (optionId: string) => [optionId, null] as const,
63
+ ),
64
+ );
65
+
66
+ for (const [optionId, choiceId] of Object.entries(
67
+ manifestProfile.optionValues ?? {},
68
+ ) as Array<[string, string]>) {
69
+ resolvedOptionValues[optionId] = choiceId;
70
+ }
71
+ for (const [optionId, choiceId] of Object.entries(
72
+ setup.optionValues ?? {},
73
+ ) as Array<[string, string]>) {
74
+ resolvedOptionValues[optionId] = choiceId ?? null;
75
+ }
76
+
77
+ return {
78
+ profileId: setup.profileId,
79
+ optionValues:
80
+ resolvedOptionValues as RuntimeSetupSelection<Manifest>["optionValues"],
81
+ };
82
+ }
83
+
84
+ function resolveInitialPhase(setup: State["runtime"]["setup"]): PhaseName {
85
+ const setupProfile = setup
86
+ ? scope.reducerSetupProfiles[setup.profileId]
87
+ : null;
88
+ const resolvedPhase = (setupProfile?.initialPhase ??
89
+ scope.defaultInitialPhase ??
90
+ scope.phaseEntries[0]?.[0]) as PhaseName | undefined;
91
+ if (!resolvedPhase) {
92
+ throw new Error("Reducer-native games must define at least one phase.");
93
+ }
94
+ if (!scope.definition.phases[resolvedPhase]) {
95
+ throw new Error(`Unknown initial phase '${resolvedPhase}'.`);
96
+ }
97
+ return resolvedPhase;
98
+ }
99
+
100
+ function applySelectedSetupBootstrap(state: State): State {
101
+ const setup = state.runtime.setup;
102
+ if (!setup) {
103
+ return state;
104
+ }
105
+
106
+ const bootstrap = scope.reducerSetupProfiles[setup.profileId]?.bootstrap;
107
+ if (!bootstrap || bootstrap.length === 0) {
108
+ return state;
109
+ }
110
+
111
+ return applySetupBootstrap(state, bootstrap) as State;
112
+ }
113
+
114
+ function initPhaseState(
115
+ state: State,
116
+ phaseName: PhaseName,
117
+ playerIds: PlayerId[],
118
+ ): State {
119
+ const phase = scope.phaseByName(phaseName);
120
+ const phaseState = phase.initialState
121
+ ? phase.initialState({
122
+ manifest: scope.definition.contract.manifest,
123
+ state,
124
+ playerIds,
125
+ setup: state.runtime.setup,
126
+ })
127
+ : safeParseOrThrow(phase.state, {}, `phase:${phaseName}:initialState`);
128
+ return {
129
+ ...state,
130
+ phase: safeParseOrThrow(
131
+ phase.state,
132
+ phaseState,
133
+ `phase:${phaseName}`,
134
+ ) as State["phase"],
135
+ flow: {
136
+ ...state.flow,
137
+ currentPhase: phaseName as State["flow"]["currentPhase"],
138
+ },
139
+ };
140
+ }
141
+
142
+ function enterPhase({
143
+ state,
144
+ phaseName,
145
+ playerIds,
146
+ event,
147
+ }: {
148
+ state: State;
149
+ phaseName: PhaseName;
150
+ playerIds: PlayerId[];
151
+ event: "initialize" | "transition";
152
+ }): {
153
+ state: State;
154
+ instructions: RuntimeInstructionForState<State>[];
155
+ } {
156
+ const workingState = initPhaseState(state, phaseName, playerIds);
157
+ const phase = scope.phaseByName(phaseName);
158
+ let nextState: State = workingState;
159
+ const instructions: RuntimeInstructionForState<State>[] = [];
160
+ if (phase.enter) {
161
+ const random = createMutableRandomHelpers(workingState.runtime.rng);
162
+ const entered = normalizeResult(
163
+ phase.enter(
164
+ scope.buildRuntimeArgs(
165
+ workingState,
166
+ {
167
+ event,
168
+ state: scope.toDomainState(workingState),
169
+ },
170
+ { random: random.random },
171
+ ),
172
+ ),
173
+ scope.toDomainState(workingState),
174
+ );
175
+ if (entered.type === "reject") {
176
+ throw new Error(
177
+ entered.message ??
178
+ (event === "initialize"
179
+ ? `Reducer phase '${phaseName}' rejected during initialization.`
180
+ : `Reducer phase '${phaseName}' rejected during phase initialization.`),
181
+ );
182
+ }
183
+ nextState = {
184
+ ...entered.state,
185
+ runtime: { ...workingState.runtime, rng: random.currentRng() },
186
+ } as State;
187
+ if (entered.instructions) instructions.push(...entered.instructions);
188
+ }
189
+
190
+ const activeStage = interactions.resolveActiveStage(nextState, phaseName);
191
+ if (activeStage?.stage.onEnter) {
192
+ const random = createMutableRandomHelpers(nextState.runtime.rng);
193
+ const stageEntered = normalizeResult(
194
+ activeStage.stage.onEnter(
195
+ scope.buildRuntimeArgs(
196
+ nextState,
197
+ {
198
+ event,
199
+ state: scope.toDomainState(nextState),
200
+ },
201
+ { random: random.random },
202
+ ),
203
+ ),
204
+ scope.toDomainState(nextState),
205
+ );
206
+ if (stageEntered.type === "reject") {
207
+ throw new Error(
208
+ stageEntered.message ??
209
+ (event === "initialize"
210
+ ? `Reducer stage '${phaseName}.${activeStage.id}' rejected during initialization.`
211
+ : `Reducer stage '${phaseName}.${activeStage.id}' rejected during stage initialization.`),
212
+ );
213
+ }
214
+ nextState = {
215
+ ...stageEntered.state,
216
+ runtime: { ...nextState.runtime, rng: random.currentRng() },
217
+ } as State;
218
+ if (stageEntered.instructions) {
219
+ instructions.push(...stageEntered.instructions);
220
+ }
221
+ }
222
+ return { state: nextState, instructions };
223
+ }
224
+
225
+ function initializePhaseResult(
226
+ state: State,
227
+ phaseName: PhaseName,
228
+ ): {
229
+ state: State;
230
+ instructions: RuntimeInstructionForState<State>[];
231
+ } {
232
+ return enterPhase({
233
+ state,
234
+ phaseName,
235
+ playerIds: scope.buildContext(state).playerOrder as PlayerId[],
236
+ event: "transition",
237
+ });
238
+ }
239
+
240
+ function createInitialState({
241
+ table,
242
+ playerIds,
243
+ rngSeed,
244
+ setup,
245
+ }: {
246
+ table: State["table"];
247
+ playerIds: PlayerId[];
248
+ rngSeed?: number | null;
249
+ setup?: RuntimeSetupSelectionInput<Manifest> | null;
250
+ }): { state: State; initialPhase: PhaseName } {
251
+ const tableWithManifestDefaults = applyManifestTableDefaults(
252
+ table,
253
+ playerIds,
254
+ );
255
+ const parsedTable = safeParseOrThrow(
256
+ scope.definition.contract.manifest.tableSchema,
257
+ tableWithManifestDefaults,
258
+ "table",
259
+ ) as State["table"];
260
+ const selectedSetup = resolveSelectedSetup(setup);
261
+ const initialSetup =
262
+ selectedSetup as RuntimeSetupSelection<ExactManifest> | null;
263
+ const initialPhase = resolveInitialPhase(selectedSetup);
264
+ const initialQueries = createStateQueries({ table: parsedTable });
265
+ return {
266
+ initialPhase,
267
+ state: {
268
+ table: parsedTable,
269
+ publicState: safeParseOrThrow(
270
+ scope.definition.contract.state.public,
271
+ scope.definition.initial?.public?.({
272
+ manifest: scope.definition.contract.manifest,
273
+ table: parsedTable,
274
+ playerIds,
275
+ rngSeed,
276
+ setup: initialSetup,
277
+ q: initialQueries,
278
+ }) ?? {},
279
+ "publicState",
280
+ ) as State["publicState"],
281
+ privateState: Object.fromEntries(
282
+ playerIds.map((playerId) => [
283
+ playerId,
284
+ safeParseOrThrow(
285
+ scope.definition.contract.state.private,
286
+ scope.definition.initial?.private?.({
287
+ manifest: scope.definition.contract.manifest,
288
+ table: parsedTable,
289
+ playerIds,
290
+ playerId,
291
+ rngSeed,
292
+ setup: initialSetup,
293
+ q: initialQueries,
294
+ }) ?? {},
295
+ `privateState:${playerId}`,
296
+ ),
297
+ ]),
298
+ ) as State["privateState"],
299
+ hiddenState: safeParseOrThrow(
300
+ scope.definition.contract.state.hidden,
301
+ scope.definition.initial?.hidden?.({
302
+ manifest: scope.definition.contract.manifest,
303
+ table: parsedTable,
304
+ playerIds,
305
+ rngSeed,
306
+ setup: initialSetup,
307
+ q: initialQueries,
308
+ }) ?? {},
309
+ "hiddenState",
310
+ ) as State["hiddenState"],
311
+ flow: {
312
+ currentPhase: initialPhase as State["flow"]["currentPhase"],
313
+ turn: 0,
314
+ round: 0,
315
+ activePlayers: [],
316
+ },
317
+ phase: {} as State["phase"],
318
+ runtime: {
319
+ rng: {
320
+ seed: rngSeed ?? null,
321
+ cursor: 0,
322
+ trace: [],
323
+ },
324
+ setup: selectedSetup,
325
+ simultaneous: { current: null },
326
+ lastTransition: null,
327
+ } as State["runtime"],
328
+ },
329
+ };
330
+ }
331
+
332
+ function applyManifestTableDefaults(
333
+ table: State["table"],
334
+ playerIds: PlayerId[],
335
+ ): State["table"] {
336
+ const manifest = scope.definition.contract.manifest;
337
+ const defaultZones = manifest.defaults.zones(playerIds);
338
+ const tableZones = table.zones ?? {};
339
+ const tableResources = table.resources;
340
+ return {
341
+ ...table,
342
+ playerOrder:
343
+ table.playerOrder && table.playerOrder.length > 0
344
+ ? table.playerOrder
345
+ : playerIds,
346
+ zones: {
347
+ ...defaultZones,
348
+ ...tableZones,
349
+ shared: {
350
+ ...(defaultZones.shared ?? {}),
351
+ ...(tableZones.shared ?? {}),
352
+ },
353
+ perPlayer: {
354
+ ...(defaultZones.perPlayer ?? {}),
355
+ ...(tableZones.perPlayer ?? {}),
356
+ },
357
+ visibility: {
358
+ ...(defaultZones.visibility ?? {}),
359
+ ...(tableZones.visibility ?? {}),
360
+ },
361
+ cardSetIdsByZoneId: {
362
+ ...(defaultZones.cardSetIdsByZoneId ?? {}),
363
+ ...(tableZones.cardSetIdsByZoneId ?? {}),
364
+ },
365
+ },
366
+ decks: {
367
+ ...manifest.defaults.decks(playerIds),
368
+ ...table.decks,
369
+ },
370
+ hands: {
371
+ ...manifest.defaults.hands(playerIds),
372
+ ...table.hands,
373
+ },
374
+ handVisibility: {
375
+ ...manifest.defaults.handVisibility(playerIds),
376
+ ...table.handVisibility,
377
+ },
378
+ ownerOfCard: {
379
+ ...manifest.defaults.ownerOfCard(playerIds),
380
+ ...table.ownerOfCard,
381
+ },
382
+ visibility: {
383
+ ...manifest.defaults.visibility(playerIds),
384
+ ...table.visibility,
385
+ },
386
+ resources:
387
+ isPerPlayer(tableResources) && tableResources.entries.length > 0
388
+ ? tableResources
389
+ : manifest.defaults.resources(playerIds),
390
+ } as State["table"];
391
+ }
392
+
393
+ function initializeSession(
394
+ input: {
395
+ table: State["table"];
396
+ playerIds: PlayerId[];
397
+ rngSeed?: number | null;
398
+ setup?: RuntimeSetupSelectionInput<Manifest> | null;
399
+ },
400
+ drainInstructions: (
401
+ state: State,
402
+ instructions: RuntimeInstructionForState<State>[],
403
+ ) => State,
404
+ ): SessionState {
405
+ const initial = createInitialState(input);
406
+ const bootstrappedState = applySelectedSetupBootstrap(initial.state);
407
+ const entered = enterPhase({
408
+ state: bootstrappedState,
409
+ phaseName: initial.initialPhase,
410
+ playerIds: input.playerIds,
411
+ event: "initialize",
412
+ });
413
+ return scope.toSessionState(
414
+ drainInstructions(entered.state, entered.instructions),
415
+ );
416
+ }
417
+
418
+ return {
419
+ createInitialState,
420
+ enterPhase,
421
+ initializePhaseResult,
422
+ initializeSession,
423
+ initPhaseState,
424
+ resolveInitialPhase,
425
+ resolveSelectedSetup,
426
+ };
427
+ }