@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,1282 @@
1
+ import type {
2
+ BoardEdgeRef,
3
+ BoardVertexRef,
4
+ DieTypeSpec as ApiDieTypeSpec,
5
+ GameTopologyManifest as ApiGameTopologyManifest,
6
+ JsonValue,
7
+ PropertySchema,
8
+ } from "./contracts.js";
9
+
10
+ type DieTypeSpec = Omit<ApiDieTypeSpec, "sides"> & {
11
+ sides?: ApiDieTypeSpec["sides"];
12
+ };
13
+
14
+ type DeepReadonly<T> = T extends (...args: readonly unknown[]) => unknown
15
+ ? T
16
+ : T extends readonly (infer Item)[]
17
+ ? ReadonlyArray<DeepReadonly<Item>>
18
+ : T extends object
19
+ ? { readonly [Key in keyof T]: DeepReadonly<T[Key]> }
20
+ : T;
21
+
22
+ type GameTopologyManifest = DeepReadonly<
23
+ Omit<ApiGameTopologyManifest, "dieTypes"> & {
24
+ dieTypes?: readonly DieTypeSpec[];
25
+ }
26
+ >;
27
+
28
+ type ArrayItem<T> = T extends readonly (infer Item)[] ? Item : never;
29
+ type EntryId<T> = T extends { id: infer Id extends string } ? Id : never;
30
+ type IdsOf<T> = EntryId<ArrayItem<NonNullable<T>>>;
31
+ type RuntimeRecord = Record<string, JsonValue>;
32
+
33
+ type CardSetId<Manifest extends GameTopologyManifest> = IdsOf<
34
+ Manifest["cardSets"]
35
+ >;
36
+ type ZoneId<Manifest extends GameTopologyManifest> = IdsOf<Manifest["zones"]>;
37
+ type BoardId<Manifest extends GameTopologyManifest> = IdsOf<Manifest["boards"]>;
38
+ type PerPlayerZoneId<Manifest extends GameTopologyManifest> = EntryId<
39
+ Extract<ArrayItem<NonNullable<Manifest["zones"]>>, { scope: "perPlayer" }>
40
+ >;
41
+ type SharedZoneId<Manifest extends GameTopologyManifest> = Exclude<
42
+ ZoneId<Manifest>,
43
+ PerPlayerZoneId<Manifest>
44
+ >;
45
+ type PerPlayerBoardId<Manifest extends GameTopologyManifest> = EntryId<
46
+ Extract<ArrayItem<NonNullable<Manifest["boards"]>>, { scope: "perPlayer" }>
47
+ >;
48
+ type SharedBoardId<Manifest extends GameTopologyManifest> = Exclude<
49
+ BoardId<Manifest>,
50
+ PerPlayerBoardId<Manifest>
51
+ >;
52
+ type ResourceId<Manifest extends GameTopologyManifest> = IdsOf<
53
+ Manifest["resources"]
54
+ >;
55
+ type PieceTypeId<Manifest extends GameTopologyManifest> = IdsOf<
56
+ Manifest["pieceTypes"]
57
+ >;
58
+ type DieTypeId<Manifest extends GameTopologyManifest> = IdsOf<
59
+ Manifest["dieTypes"]
60
+ >;
61
+ type PieceSeedOf<Manifest extends GameTopologyManifest> = ArrayItem<
62
+ NonNullable<Manifest["pieceSeeds"]>
63
+ >;
64
+ type DieSeedOf<Manifest extends GameTopologyManifest> = ArrayItem<
65
+ NonNullable<Manifest["dieSeeds"]>
66
+ >;
67
+ type SetupOptionId<Manifest extends GameTopologyManifest> = IdsOf<
68
+ Manifest["setupOptions"]
69
+ >;
70
+ type ManualCardSetOf<Manifest extends GameTopologyManifest> = Extract<
71
+ ArrayItem<NonNullable<Manifest["cardSets"]>>,
72
+ { type: "manual" }
73
+ >;
74
+ type CardOf<Manifest extends GameTopologyManifest> =
75
+ ManualCardSetOf<Manifest> extends infer CardSet
76
+ ? CardSet extends { cards: infer Cards extends readonly unknown[] }
77
+ ? ArrayItem<Cards>
78
+ : never
79
+ : never;
80
+
81
+ type BoardOf<
82
+ Manifest extends GameTopologyManifest,
83
+ CurrentBoardId extends BoardId<Manifest>,
84
+ > = Extract<ArrayItem<NonNullable<Manifest["boards"]>>, { id: CurrentBoardId }>;
85
+ type BoardTemplateOf<
86
+ Manifest extends GameTopologyManifest,
87
+ CurrentTemplateId extends string,
88
+ > = Extract<
89
+ ArrayItem<NonNullable<Manifest["boardTemplates"]>>,
90
+ { id: CurrentTemplateId }
91
+ >;
92
+ type ResolvedBoardLikeOf<
93
+ Manifest extends GameTopologyManifest,
94
+ CurrentBoardId extends BoardId<Manifest>,
95
+ > =
96
+ | BoardOf<Manifest, CurrentBoardId>
97
+ | (BoardOf<Manifest, CurrentBoardId> extends {
98
+ templateId: infer CurrentTemplateId extends string;
99
+ }
100
+ ? BoardTemplateOf<Manifest, CurrentTemplateId>
101
+ : never);
102
+
103
+ type SpaceIdOf<BoardLike> = IdsOf<
104
+ BoardLike extends { spaces?: infer Spaces } ? Spaces : never
105
+ >;
106
+ type ContainerIdOf<BoardLike> = IdsOf<
107
+ BoardLike extends { containers?: infer Containers } ? Containers : never
108
+ >;
109
+ type SpaceOf<BoardLike> = ArrayItem<
110
+ NonNullable<BoardLike extends { spaces?: infer Spaces } ? Spaces : never>
111
+ >;
112
+ type SquareSpaceOf<BoardLike> = Extract<
113
+ SpaceOf<BoardLike>,
114
+ { row: number; col: number }
115
+ >;
116
+ type HexSpaceOf<BoardLike> = Extract<
117
+ SpaceOf<BoardLike>,
118
+ { q: number; r: number }
119
+ >;
120
+ type BoardEntryOf<Manifest extends GameTopologyManifest> = ArrayItem<
121
+ NonNullable<Manifest["boards"]>
122
+ >;
123
+ type TemplateForBoardEntry<
124
+ Manifest extends GameTopologyManifest,
125
+ Entry,
126
+ > = Entry extends {
127
+ templateId: infer TemplateId extends string;
128
+ layout: infer Layout;
129
+ }
130
+ ? Extract<BoardTemplateOf<Manifest, TemplateId>, { layout: Layout }>
131
+ : never;
132
+ type BoardLikeForEntry<Manifest extends GameTopologyManifest, Entry> =
133
+ Entry extends BoardEntryOf<Manifest>
134
+ ? Entry extends { id: infer CurrentBoardId extends BoardId<Manifest> }
135
+ ? ResolvedBoardLikeOf<Manifest, CurrentBoardId>
136
+ : Entry
137
+ : Entry;
138
+
139
+ type SpaceIdForBoard<
140
+ Manifest extends GameTopologyManifest,
141
+ CurrentBoardId extends BoardId<Manifest>,
142
+ > = SpaceIdOf<ResolvedBoardLikeOf<Manifest, CurrentBoardId>>;
143
+ type ContainerIdForBoard<
144
+ Manifest extends GameTopologyManifest,
145
+ CurrentBoardId extends BoardId<Manifest>,
146
+ > = ContainerIdOf<ResolvedBoardLikeOf<Manifest, CurrentBoardId>>;
147
+
148
+ type RuntimeIdsFromCount<BaseId extends string, Count> = Count extends number
149
+ ? number extends Count
150
+ ? BaseId | `${BaseId}-${number}`
151
+ : Count extends 1
152
+ ? BaseId
153
+ : `${BaseId}-${OneTo<Count>}`
154
+ : BaseId;
155
+
156
+ type CardRuntimeId<Card> = Card extends { type: infer TypeId extends string }
157
+ ? RuntimeIdsFromCount<
158
+ TypeId,
159
+ Card extends { count: infer Count extends number } ? Count : never
160
+ >
161
+ : never;
162
+ type SeedRuntimeId<Seed> = Seed extends { typeId: infer TypeId extends string }
163
+ ? RuntimeIdsFromCount<
164
+ Seed extends { id: infer Id extends string } ? Id : TypeId,
165
+ Seed extends { count: infer Count extends number } ? Count : never
166
+ >
167
+ : never;
168
+ type CardId<Manifest extends GameTopologyManifest> = CardRuntimeId<
169
+ CardOf<Manifest>
170
+ >;
171
+ type PieceId<Manifest extends GameTopologyManifest> = SeedRuntimeId<
172
+ PieceSeedOf<Manifest>
173
+ >;
174
+ type DieId<Manifest extends GameTopologyManifest> = SeedRuntimeId<
175
+ DieSeedOf<Manifest>
176
+ >;
177
+
178
+ type PieceTypeOf<
179
+ Manifest extends GameTopologyManifest,
180
+ CurrentTypeId extends PieceTypeId<Manifest>,
181
+ > = Extract<
182
+ ArrayItem<NonNullable<Manifest["pieceTypes"]>>,
183
+ { id: CurrentTypeId }
184
+ >;
185
+ type DieTypeOf<
186
+ Manifest extends GameTopologyManifest,
187
+ CurrentTypeId extends DieTypeId<Manifest>,
188
+ > = Extract<
189
+ ArrayItem<NonNullable<Manifest["dieTypes"]>>,
190
+ { id: CurrentTypeId }
191
+ >;
192
+ type SlotIdOf<TypeSpec> = IdsOf<
193
+ TypeSpec extends { slots?: infer Slots } ? Slots : never
194
+ >;
195
+ type SlotIdForPieceType<
196
+ Manifest extends GameTopologyManifest,
197
+ CurrentTypeId extends PieceTypeId<Manifest>,
198
+ > = SlotIdOf<PieceTypeOf<Manifest, CurrentTypeId>>;
199
+ type SlotIdForDieType<
200
+ Manifest extends GameTopologyManifest,
201
+ CurrentTypeId extends DieTypeId<Manifest>,
202
+ > = SlotIdOf<DieTypeOf<Manifest, CurrentTypeId>>;
203
+
204
+ type SingletonExplicitSeed<Seed> = Seed extends { id: infer _Id extends string }
205
+ ? Seed extends { count: infer Count extends number }
206
+ ? Count extends 1
207
+ ? Seed
208
+ : never
209
+ : Seed
210
+ : never;
211
+ type TypedPieceSlotHostSeed<Manifest extends GameTopologyManifest> =
212
+ SingletonExplicitSeed<PieceSeedOf<Manifest>> extends infer Seed
213
+ ? Seed extends { typeId: infer CurrentTypeId extends PieceTypeId<Manifest> }
214
+ ? [SlotIdForPieceType<Manifest, CurrentTypeId>] extends [never]
215
+ ? never
216
+ : Seed
217
+ : never
218
+ : never;
219
+ type TypedDieSlotHostSeed<Manifest extends GameTopologyManifest> =
220
+ SingletonExplicitSeed<DieSeedOf<Manifest>> extends infer Seed
221
+ ? Seed extends { typeId: infer CurrentTypeId extends DieTypeId<Manifest> }
222
+ ? [SlotIdForDieType<Manifest, CurrentTypeId>] extends [never]
223
+ ? never
224
+ : Seed
225
+ : never
226
+ : never;
227
+
228
+ type TypedPieceSlotHomeSpec<Manifest extends GameTopologyManifest> =
229
+ TypedPieceSlotHostSeed<Manifest> extends infer Seed
230
+ ? Seed extends {
231
+ id: infer HostId extends string;
232
+ typeId: infer CurrentTypeId extends PieceTypeId<Manifest>;
233
+ }
234
+ ? {
235
+ type: "slot";
236
+ host: {
237
+ kind: "piece";
238
+ id: HostId;
239
+ };
240
+ slotId: SlotIdForPieceType<Manifest, CurrentTypeId>;
241
+ }
242
+ : never
243
+ : never;
244
+ type TypedDieSlotHomeSpec<Manifest extends GameTopologyManifest> =
245
+ TypedDieSlotHostSeed<Manifest> extends infer Seed
246
+ ? Seed extends {
247
+ id: infer HostId extends string;
248
+ typeId: infer CurrentTypeId extends DieTypeId<Manifest>;
249
+ }
250
+ ? {
251
+ type: "slot";
252
+ host: {
253
+ kind: "die";
254
+ id: HostId;
255
+ };
256
+ slotId: SlotIdForDieType<Manifest, CurrentTypeId>;
257
+ }
258
+ : never
259
+ : never;
260
+
261
+ type RequiredSchemaKeys<Properties extends Readonly<Record<string, unknown>>> =
262
+ {
263
+ [Key in keyof Properties]: Properties[Key] extends { optional: true }
264
+ ? never
265
+ : Properties[Key] extends { default: unknown }
266
+ ? never
267
+ : Key;
268
+ }[keyof Properties];
269
+ type OptionalSchemaKeys<Properties extends Readonly<Record<string, unknown>>> =
270
+ {
271
+ [Key in keyof Properties]: Properties[Key] extends { optional: true }
272
+ ? Key
273
+ : Properties[Key] extends { default: unknown }
274
+ ? Key
275
+ : never;
276
+ }[keyof Properties];
277
+
278
+ type SchemaValueFromObjectProperties<
279
+ Properties extends Readonly<Record<string, unknown>>,
280
+ Manifest extends GameTopologyManifest,
281
+ BoardLike = never,
282
+ > = keyof Properties extends never
283
+ ? RuntimeRecord
284
+ : {
285
+ [Key in RequiredSchemaKeys<Properties>]: SchemaValueForProperty<
286
+ Properties[Key],
287
+ Manifest,
288
+ BoardLike
289
+ >;
290
+ } & {
291
+ [Key in OptionalSchemaKeys<Properties>]?: SchemaValueForProperty<
292
+ Properties[Key],
293
+ Manifest,
294
+ BoardLike
295
+ >;
296
+ };
297
+
298
+ type SchemaValueForObjectSchema<
299
+ Schema,
300
+ Manifest extends GameTopologyManifest,
301
+ BoardLike = never,
302
+ > = Schema extends {
303
+ properties: infer Properties extends Readonly<Record<string, unknown>>;
304
+ }
305
+ ? SchemaValueFromObjectProperties<Properties, Manifest, BoardLike>
306
+ : RuntimeRecord;
307
+
308
+ type MergeSharedProperties<Variant, Shared> = Variant extends {
309
+ properties: infer VariantProperties extends Readonly<Record<string, unknown>>;
310
+ }
311
+ ? {
312
+ properties: Shared extends Readonly<Record<string, unknown>>
313
+ ? Omit<Shared, keyof VariantProperties> & VariantProperties
314
+ : VariantProperties;
315
+ }
316
+ : Variant;
317
+
318
+ type BaseSchemaValueForProperty<
319
+ Schema,
320
+ Manifest extends GameTopologyManifest,
321
+ BoardLike = never,
322
+ > = Schema extends { type: "string" }
323
+ ? string
324
+ : Schema extends { type: "integer" | "number" }
325
+ ? number
326
+ : Schema extends { type: "boolean" }
327
+ ? boolean
328
+ : Schema extends { type: "zoneId" }
329
+ ? ZoneId<Manifest>
330
+ : Schema extends { type: "cardId" }
331
+ ? CardId<Manifest>
332
+ : Schema extends { type: "playerId" }
333
+ ? PlayerId<Manifest>
334
+ : Schema extends { type: "boardId" }
335
+ ? BoardId<Manifest>
336
+ : Schema extends { type: "spaceId" }
337
+ ? [BoardLike] extends [never]
338
+ ? string
339
+ : SpaceIdOf<BoardLike>
340
+ : Schema extends { type: "edgeId" }
341
+ ? [BoardLike] extends [never]
342
+ ? string
343
+ : DerivedEdgeIdOf<BoardLike>
344
+ : Schema extends { type: "vertexId" }
345
+ ? [BoardLike] extends [never]
346
+ ? string
347
+ : DerivedVertexIdOf<BoardLike>
348
+ : Schema extends { type: "pieceId" }
349
+ ? PieceId<Manifest>
350
+ : Schema extends { type: "dieId" }
351
+ ? DieId<Manifest>
352
+ : Schema extends { type: "resourceId" }
353
+ ? ResourceId<Manifest>
354
+ : Schema extends { type: "enum" }
355
+ ? Schema extends {
356
+ enums: infer Values extends readonly string[];
357
+ }
358
+ ? Values[number]
359
+ : string
360
+ : Schema extends { type: "array" }
361
+ ? ReadonlyArray<
362
+ SchemaValueForProperty<
363
+ Schema extends {
364
+ items?: infer Items;
365
+ }
366
+ ? Items
367
+ : undefined,
368
+ Manifest,
369
+ BoardLike
370
+ >
371
+ >
372
+ : Schema extends { type: "object" }
373
+ ? SchemaValueForObjectSchema<
374
+ Schema extends {
375
+ properties?: infer Properties extends
376
+ Record<string, unknown>;
377
+ }
378
+ ? {
379
+ properties: Properties;
380
+ }
381
+ : undefined,
382
+ Manifest,
383
+ BoardLike
384
+ >
385
+ : Schema extends { type: "record" }
386
+ ? Record<
387
+ string,
388
+ SchemaValueForProperty<
389
+ Schema extends {
390
+ values?: infer Values;
391
+ }
392
+ ? Values
393
+ : undefined,
394
+ Manifest,
395
+ BoardLike
396
+ >
397
+ >
398
+ : RuntimeRecord;
399
+
400
+ type SchemaValueForProperty<
401
+ Schema,
402
+ Manifest extends GameTopologyManifest,
403
+ BoardLike = never,
404
+ > = Schema extends { nullable: true }
405
+ ? BaseSchemaValueForProperty<Schema, Manifest, BoardLike> | null
406
+ : BaseSchemaValueForProperty<Schema, Manifest, BoardLike>;
407
+
408
+ type BuildTuple<
409
+ Length extends number,
410
+ Accumulator extends unknown[] = [],
411
+ > = Accumulator["length"] extends Length
412
+ ? Accumulator
413
+ : BuildTuple<Length, [...Accumulator, unknown]>;
414
+
415
+ type EnumerateInternal<
416
+ Length extends number,
417
+ Accumulator extends number[] = [],
418
+ > = Accumulator["length"] extends Length
419
+ ? Accumulator[number]
420
+ : EnumerateInternal<Length, [...Accumulator, Accumulator["length"]]>;
421
+
422
+ type AddOne<Count extends number> = [...BuildTuple<Count>, unknown]["length"] &
423
+ number;
424
+ type OneTo<Count extends number> = Exclude<EnumerateInternal<AddOne<Count>>, 0>;
425
+ type PlayerId<Manifest extends GameTopologyManifest> =
426
+ Manifest["players"]["maxPlayers"] extends infer MaxPlayers extends number
427
+ ? `player-${OneTo<MaxPlayers>}`
428
+ : `player-${number}`;
429
+
430
+ type ToNumber<Input extends string> =
431
+ Input extends `${infer Value extends number}` ? Value : never;
432
+ type AbsoluteNumber<Count extends number> =
433
+ `${Count}` extends `-${infer Value extends number}` ? Value : Count;
434
+ type IsNegative<Count extends number> = `${Count}` extends `-${string}`
435
+ ? true
436
+ : false;
437
+ type Negate<Count extends number> = Count extends 0
438
+ ? 0
439
+ : ToNumber<`${`${Count}` extends `-${infer Value extends number}`
440
+ ? Value
441
+ : `-${Count}`}`>;
442
+ type AddPositive<Left extends number, Right extends number> = number extends
443
+ | Left
444
+ | Right
445
+ ? number
446
+ : [...BuildTuple<Left>, ...BuildTuple<Right>]["length"] & number;
447
+ type ComparePositive<
448
+ Left extends number,
449
+ Right extends number,
450
+ > = Left extends Right
451
+ ? "equal"
452
+ : number extends Left | Right
453
+ ? "unknown"
454
+ : BuildTuple<Left> extends [...BuildTuple<Right>, ...infer Rest]
455
+ ? Rest extends []
456
+ ? "equal"
457
+ : "greater"
458
+ : "less";
459
+ type SubtractPositive<
460
+ Left extends number,
461
+ Right extends number,
462
+ > = number extends Left | Right
463
+ ? number
464
+ : BuildTuple<Left> extends [...BuildTuple<Right>, ...infer Rest]
465
+ ? Rest["length"] & number
466
+ : never;
467
+ type AddSigned<Left extends number, Right extends number> = number extends
468
+ | Left
469
+ | Right
470
+ ? number
471
+ : IsNegative<Left> extends IsNegative<Right>
472
+ ? IsNegative<Left> extends true
473
+ ? Negate<AddPositive<AbsoluteNumber<Left>, AbsoluteNumber<Right>>>
474
+ : AddPositive<AbsoluteNumber<Left>, AbsoluteNumber<Right>>
475
+ : ComparePositive<
476
+ AbsoluteNumber<Left>,
477
+ AbsoluteNumber<Right>
478
+ > extends "equal"
479
+ ? 0
480
+ : ComparePositive<
481
+ AbsoluteNumber<Left>,
482
+ AbsoluteNumber<Right>
483
+ > extends "greater"
484
+ ? IsNegative<Left> extends true
485
+ ? Negate<
486
+ SubtractPositive<AbsoluteNumber<Left>, AbsoluteNumber<Right>>
487
+ >
488
+ : SubtractPositive<AbsoluteNumber<Left>, AbsoluteNumber<Right>>
489
+ : IsNegative<Right> extends true
490
+ ? Negate<
491
+ SubtractPositive<AbsoluteNumber<Right>, AbsoluteNumber<Left>>
492
+ >
493
+ : SubtractPositive<AbsoluteNumber<Right>, AbsoluteNumber<Left>>;
494
+ type MultiplyByThree<Count extends number> = AddSigned<
495
+ Count,
496
+ AddSigned<Count, Count>
497
+ >;
498
+ type CharRank<Character extends string> = Character extends ","
499
+ ? 0
500
+ : Character extends "-"
501
+ ? 1
502
+ : Character extends "0"
503
+ ? 2
504
+ : Character extends "1"
505
+ ? 3
506
+ : Character extends "2"
507
+ ? 4
508
+ : Character extends "3"
509
+ ? 5
510
+ : Character extends "4"
511
+ ? 6
512
+ : Character extends "5"
513
+ ? 7
514
+ : Character extends "6"
515
+ ? 8
516
+ : Character extends "7"
517
+ ? 9
518
+ : Character extends "8"
519
+ ? 10
520
+ : Character extends "9"
521
+ ? 11
522
+ : never;
523
+ type CompareCharacters<
524
+ Left extends string,
525
+ Right extends string,
526
+ > = Left extends Right
527
+ ? "equal"
528
+ : ComparePositive<CharRank<Left>, CharRank<Right>> extends "less"
529
+ ? "less"
530
+ : "greater";
531
+ type CompareStrings<
532
+ Left extends string,
533
+ Right extends string,
534
+ > = Left extends `${infer LeftHead}${infer LeftTail}`
535
+ ? Right extends `${infer RightHead}${infer RightTail}`
536
+ ? LeftHead extends RightHead
537
+ ? CompareStrings<LeftTail, RightTail>
538
+ : CompareCharacters<LeftHead, RightHead>
539
+ : "greater"
540
+ : Right extends ""
541
+ ? "equal"
542
+ : "less";
543
+ type SortPair<Left extends string, Right extends string> =
544
+ CompareStrings<Left, Right> extends "greater"
545
+ ? `${Right}::${Left}`
546
+ : `${Left}::${Right}`;
547
+ type SquareCornerGeometryKey<
548
+ Space extends { row: number; col: number },
549
+ Corner extends "nw" | "ne" | "se" | "sw",
550
+ > = Corner extends "nw"
551
+ ? `${Space["col"]},${Space["row"]}`
552
+ : Corner extends "ne"
553
+ ? `${AddSigned<Space["col"], 1>},${Space["row"]}`
554
+ : Corner extends "se"
555
+ ? `${AddSigned<Space["col"], 1>},${AddSigned<Space["row"], 1>}`
556
+ : `${Space["col"]},${AddSigned<Space["row"], 1>}`;
557
+ type SquareEdgeGeometryKey<
558
+ Space extends { row: number; col: number },
559
+ Side extends "north" | "east" | "south" | "west",
560
+ > = Side extends "north"
561
+ ? `${Space["col"]},${Space["row"]}::${AddSigned<Space["col"], 1>},${Space["row"]}`
562
+ : Side extends "east"
563
+ ? `${AddSigned<Space["col"], 1>},${Space["row"]}::${AddSigned<
564
+ Space["col"],
565
+ 1
566
+ >},${AddSigned<Space["row"], 1>}`
567
+ : Side extends "south"
568
+ ? `${Space["col"]},${AddSigned<Space["row"], 1>}::${AddSigned<
569
+ Space["col"],
570
+ 1
571
+ >},${AddSigned<Space["row"], 1>}`
572
+ : `${Space["col"]},${Space["row"]}::${Space["col"]},${AddSigned<
573
+ Space["row"],
574
+ 1
575
+ >}`;
576
+ type HexCornerGeometryKey<
577
+ Space extends { q: number; r: number },
578
+ Corner extends "ne-e" | "e-se" | "se-sw" | "sw-w" | "w-nw" | "nw-ne",
579
+ > = `${AddSigned<
580
+ MultiplyByThree<Space["q"]>,
581
+ Corner extends "ne-e"
582
+ ? 2
583
+ : Corner extends "e-se"
584
+ ? 1
585
+ : Corner extends "se-sw"
586
+ ? -1
587
+ : Corner extends "sw-w"
588
+ ? -2
589
+ : Corner extends "w-nw"
590
+ ? -1
591
+ : 1
592
+ >},${AddSigned<
593
+ MultiplyByThree<Negate<AddSigned<Space["q"], Space["r"]>>>,
594
+ Corner extends "ne-e"
595
+ ? -1
596
+ : Corner extends "e-se"
597
+ ? -2
598
+ : Corner extends "se-sw"
599
+ ? -1
600
+ : Corner extends "sw-w"
601
+ ? 1
602
+ : Corner extends "w-nw"
603
+ ? 2
604
+ : 1
605
+ >},${AddSigned<
606
+ MultiplyByThree<Space["r"]>,
607
+ Corner extends "ne-e"
608
+ ? -1
609
+ : Corner extends "e-se"
610
+ ? 1
611
+ : Corner extends "se-sw"
612
+ ? 2
613
+ : Corner extends "sw-w"
614
+ ? 1
615
+ : Corner extends "w-nw"
616
+ ? -1
617
+ : -2
618
+ >}`;
619
+ type HexEdgeGeometryKey<
620
+ Space extends { q: number; r: number },
621
+ Side extends "e" | "ne" | "nw" | "w" | "sw" | "se",
622
+ > = SortPair<
623
+ HexCornerGeometryKey<
624
+ Space,
625
+ Side extends "e"
626
+ ? "ne-e"
627
+ : Side extends "ne"
628
+ ? "nw-ne"
629
+ : Side extends "nw"
630
+ ? "w-nw"
631
+ : Side extends "w"
632
+ ? "sw-w"
633
+ : Side extends "sw"
634
+ ? "se-sw"
635
+ : "e-se"
636
+ >,
637
+ HexCornerGeometryKey<
638
+ Space,
639
+ Side extends "e"
640
+ ? "e-se"
641
+ : Side extends "ne"
642
+ ? "ne-e"
643
+ : Side extends "nw"
644
+ ? "nw-ne"
645
+ : Side extends "w"
646
+ ? "w-nw"
647
+ : Side extends "sw"
648
+ ? "sw-w"
649
+ : "se-sw"
650
+ >
651
+ >;
652
+ type DerivedSquareEdgeIdOf<BoardLike> =
653
+ SquareSpaceOf<BoardLike> extends infer Space
654
+ ? Space extends { row: number; col: number }
655
+ ?
656
+ | `square-edge:${SquareEdgeGeometryKey<Space, "north">}`
657
+ | `square-edge:${SquareEdgeGeometryKey<Space, "east">}`
658
+ | `square-edge:${SquareEdgeGeometryKey<Space, "south">}`
659
+ | `square-edge:${SquareEdgeGeometryKey<Space, "west">}`
660
+ : never
661
+ : never;
662
+ type DerivedSquareVertexIdOf<BoardLike> =
663
+ SquareSpaceOf<BoardLike> extends infer Space
664
+ ? Space extends { row: number; col: number }
665
+ ?
666
+ | `square-vertex:${SquareCornerGeometryKey<Space, "nw">}`
667
+ | `square-vertex:${SquareCornerGeometryKey<Space, "ne">}`
668
+ | `square-vertex:${SquareCornerGeometryKey<Space, "se">}`
669
+ | `square-vertex:${SquareCornerGeometryKey<Space, "sw">}`
670
+ : never
671
+ : never;
672
+ type DerivedHexEdgeIdOf<BoardLike> =
673
+ HexSpaceOf<BoardLike> extends infer Space
674
+ ? Space extends { q: number; r: number }
675
+ ?
676
+ | `hex-edge:${HexEdgeGeometryKey<Space, "e">}`
677
+ | `hex-edge:${HexEdgeGeometryKey<Space, "ne">}`
678
+ | `hex-edge:${HexEdgeGeometryKey<Space, "nw">}`
679
+ | `hex-edge:${HexEdgeGeometryKey<Space, "w">}`
680
+ | `hex-edge:${HexEdgeGeometryKey<Space, "sw">}`
681
+ | `hex-edge:${HexEdgeGeometryKey<Space, "se">}`
682
+ : never
683
+ : never;
684
+ type DerivedHexVertexIdOf<BoardLike> =
685
+ HexSpaceOf<BoardLike> extends infer Space
686
+ ? Space extends { q: number; r: number }
687
+ ?
688
+ | `hex-vertex:${HexCornerGeometryKey<Space, "ne-e">}`
689
+ | `hex-vertex:${HexCornerGeometryKey<Space, "e-se">}`
690
+ | `hex-vertex:${HexCornerGeometryKey<Space, "se-sw">}`
691
+ | `hex-vertex:${HexCornerGeometryKey<Space, "sw-w">}`
692
+ | `hex-vertex:${HexCornerGeometryKey<Space, "w-nw">}`
693
+ | `hex-vertex:${HexCornerGeometryKey<Space, "nw-ne">}`
694
+ : never
695
+ : never;
696
+ type DerivedEdgeIdOf<BoardLike> = BoardLike extends { layout: "square" }
697
+ ? DerivedSquareEdgeIdOf<BoardLike>
698
+ : BoardLike extends { layout: "hex" }
699
+ ? DerivedHexEdgeIdOf<BoardLike>
700
+ : never;
701
+ type DerivedVertexIdOf<BoardLike> = BoardLike extends { layout: "square" }
702
+ ? DerivedSquareVertexIdOf<BoardLike>
703
+ : BoardLike extends { layout: "hex" }
704
+ ? DerivedHexVertexIdOf<BoardLike>
705
+ : never;
706
+
707
+ type SetupOptionChoiceId<Option> = IdsOf<
708
+ Option extends { choices?: infer Choices } ? Choices : never
709
+ >;
710
+ type SetupOptionOf<Manifest extends GameTopologyManifest> = ArrayItem<
711
+ NonNullable<Manifest["setupOptions"]>
712
+ >;
713
+ type SetupOptionChoiceIdFor<
714
+ Manifest extends GameTopologyManifest,
715
+ OptionId extends SetupOptionId<Manifest>,
716
+ > = SetupOptionChoiceId<Extract<SetupOptionOf<Manifest>, { id: OptionId }>>;
717
+
718
+ type TypedSharedSpaceHomeSpec<Manifest extends GameTopologyManifest> = {
719
+ [CurrentBoardId in SharedBoardId<Manifest>]: {
720
+ type: "space";
721
+ boardId: CurrentBoardId;
722
+ spaceId: SpaceIdForBoard<Manifest, CurrentBoardId>;
723
+ };
724
+ }[SharedBoardId<Manifest>];
725
+
726
+ type TypedPerPlayerSpaceHomeSpec<Manifest extends GameTopologyManifest> = {
727
+ [CurrentBoardId in PerPlayerBoardId<Manifest>]: {
728
+ type: "space";
729
+ boardId: CurrentBoardId;
730
+ spaceId: SpaceIdForBoard<Manifest, CurrentBoardId>;
731
+ };
732
+ }[PerPlayerBoardId<Manifest>];
733
+
734
+ type TypedSharedContainerHomeSpec<Manifest extends GameTopologyManifest> = {
735
+ [CurrentBoardId in SharedBoardId<Manifest>]: {
736
+ type: "container";
737
+ boardId: CurrentBoardId;
738
+ containerId: ContainerIdForBoard<Manifest, CurrentBoardId>;
739
+ };
740
+ }[SharedBoardId<Manifest>];
741
+
742
+ type TypedPerPlayerContainerHomeSpec<Manifest extends GameTopologyManifest> = {
743
+ [CurrentBoardId in PerPlayerBoardId<Manifest>]: {
744
+ type: "container";
745
+ boardId: CurrentBoardId;
746
+ containerId: ContainerIdForBoard<Manifest, CurrentBoardId>;
747
+ };
748
+ }[PerPlayerBoardId<Manifest>];
749
+
750
+ type TypedSharedEdgeHomeSpec<Manifest extends GameTopologyManifest> = {
751
+ [CurrentBoardId in SharedBoardId<Manifest>]: {
752
+ type: "edge";
753
+ boardId: CurrentBoardId;
754
+ ref: BoardEdgeRef;
755
+ };
756
+ }[SharedBoardId<Manifest>];
757
+
758
+ type TypedPerPlayerEdgeHomeSpec<Manifest extends GameTopologyManifest> = {
759
+ [CurrentBoardId in PerPlayerBoardId<Manifest>]: {
760
+ type: "edge";
761
+ boardId: CurrentBoardId;
762
+ ref: BoardEdgeRef;
763
+ };
764
+ }[PerPlayerBoardId<Manifest>];
765
+
766
+ type TypedSharedVertexHomeSpec<Manifest extends GameTopologyManifest> = {
767
+ [CurrentBoardId in SharedBoardId<Manifest>]: {
768
+ type: "vertex";
769
+ boardId: CurrentBoardId;
770
+ ref: BoardVertexRef;
771
+ };
772
+ }[SharedBoardId<Manifest>];
773
+
774
+ type TypedPerPlayerVertexHomeSpec<Manifest extends GameTopologyManifest> = {
775
+ [CurrentBoardId in PerPlayerBoardId<Manifest>]: {
776
+ type: "vertex";
777
+ boardId: CurrentBoardId;
778
+ ref: BoardVertexRef;
779
+ };
780
+ }[PerPlayerBoardId<Manifest>];
781
+
782
+ type TypedSharedZoneHomeSpec<Manifest extends GameTopologyManifest> = {
783
+ type: "zone";
784
+ zoneId: SharedZoneId<Manifest>;
785
+ };
786
+
787
+ type TypedPerPlayerZoneHomeSpec<Manifest extends GameTopologyManifest> = {
788
+ type: "zone";
789
+ zoneId: PerPlayerZoneId<Manifest>;
790
+ };
791
+
792
+ type TypedPlayerScopedComponentHomeSpec<Manifest extends GameTopologyManifest> =
793
+
794
+ | TypedPerPlayerZoneHomeSpec<Manifest>
795
+ | TypedPerPlayerSpaceHomeSpec<Manifest>
796
+ | TypedPerPlayerContainerHomeSpec<Manifest>
797
+ | TypedPerPlayerEdgeHomeSpec<Manifest>
798
+ | TypedPerPlayerVertexHomeSpec<Manifest>;
799
+
800
+ type TypedSharedComponentHomeSpec<Manifest extends GameTopologyManifest> =
801
+ | { type: "detached" }
802
+ | TypedSharedZoneHomeSpec<Manifest>
803
+ | TypedSharedSpaceHomeSpec<Manifest>
804
+ | TypedSharedContainerHomeSpec<Manifest>
805
+ | TypedSharedEdgeHomeSpec<Manifest>
806
+ | TypedSharedVertexHomeSpec<Manifest>
807
+ | TypedPieceSlotHomeSpec<Manifest>
808
+ | TypedDieSlotHomeSpec<Manifest>;
809
+
810
+ type TypedComponentHomeSpec<Manifest extends GameTopologyManifest> =
811
+ | TypedSharedComponentHomeSpec<Manifest>
812
+ | TypedPlayerScopedComponentHomeSpec<Manifest>;
813
+
814
+ type TypedSeedLocationSpec<
815
+ Seed,
816
+ Manifest extends GameTopologyManifest,
817
+ > = Seed extends { home: infer Home }
818
+ ? Home extends TypedPlayerScopedComponentHomeSpec<Manifest>
819
+ ? Omit<Seed, "ownerId" | "home"> & {
820
+ ownerId: PlayerId<Manifest>;
821
+ home: TypedPlayerScopedComponentHomeSpec<Manifest>;
822
+ }
823
+ : Omit<Seed, "ownerId" | "home"> & {
824
+ ownerId?: PlayerId<Manifest>;
825
+ home?: TypedComponentHomeSpec<Manifest>;
826
+ }
827
+ : Omit<Seed, "ownerId" | "home"> & {
828
+ ownerId?: PlayerId<Manifest>;
829
+ home?: TypedComponentHomeSpec<Manifest>;
830
+ };
831
+
832
+ type TypedVisibilitySpec<Manifest extends GameTopologyManifest> = {
833
+ faceUp?: boolean;
834
+ visibleTo?: readonly PlayerId<Manifest>[];
835
+ };
836
+ type TypedVisibility<T, Manifest extends GameTopologyManifest> = T extends {
837
+ visibility?: unknown;
838
+ }
839
+ ? Omit<T, "visibility"> & {
840
+ visibility?: TypedVisibilitySpec<Manifest>;
841
+ }
842
+ : T;
843
+ type TypedFields<
844
+ T,
845
+ Schema,
846
+ Manifest extends GameTopologyManifest,
847
+ BoardLike = never,
848
+ > = T extends { fields?: unknown }
849
+ ? Omit<T, "fields"> & {
850
+ fields?: SchemaValueForObjectSchema<Schema, Manifest, BoardLike>;
851
+ }
852
+ : T;
853
+ type TypedBoardContainerHost<Host, BoardLike> = Host extends {
854
+ type: "space";
855
+ spaceId: string;
856
+ }
857
+ ? Omit<Host, "spaceId"> & {
858
+ spaceId: SpaceIdOf<BoardLike>;
859
+ }
860
+ : Host;
861
+ type TypedBoardContainer<
862
+ Container,
863
+ Manifest extends GameTopologyManifest,
864
+ BoardLike,
865
+ ContainerSchema,
866
+ > = Container extends { host: infer Host }
867
+ ? Omit<
868
+ TypedFields<
869
+ TypedAllowedCardSetIds<Container, Manifest>,
870
+ ContainerSchema,
871
+ Manifest,
872
+ BoardLike
873
+ >,
874
+ "host"
875
+ > & {
876
+ host: TypedBoardContainerHost<Host, BoardLike>;
877
+ }
878
+ : TypedFields<
879
+ TypedAllowedCardSetIds<Container, Manifest>,
880
+ ContainerSchema,
881
+ Manifest,
882
+ BoardLike
883
+ >;
884
+ type TypedBoardRelation<
885
+ Relation,
886
+ Manifest extends GameTopologyManifest,
887
+ BoardLike,
888
+ RelationSchema,
889
+ > = Relation extends object
890
+ ? Omit<
891
+ TypedFields<Relation, RelationSchema, Manifest, BoardLike>,
892
+ "fromSpaceId" | "toSpaceId"
893
+ > & {
894
+ fromSpaceId: SpaceIdOf<BoardLike>;
895
+ toSpaceId: SpaceIdOf<BoardLike>;
896
+ }
897
+ : Relation;
898
+ type TypedOptionalArray<
899
+ Base,
900
+ Source,
901
+ Key extends string,
902
+ Item,
903
+ > = Source extends { [Property in Key]?: readonly unknown[] }
904
+ ? Base & {
905
+ [Property in Key]?: ReadonlyArray<Item>;
906
+ }
907
+ : Base;
908
+ type EffectiveSchemaForEntry<
909
+ Manifest extends GameTopologyManifest,
910
+ Entry,
911
+ Key extends string,
912
+ > = Key extends keyof Entry
913
+ ? Entry[Key]
914
+ : TemplateForBoardEntry<Manifest, Entry> extends infer Template
915
+ ? Key extends keyof Template
916
+ ? Template[Key]
917
+ : undefined
918
+ : undefined;
919
+ type TypedGenericBoardLike<
920
+ Entry,
921
+ Manifest extends GameTopologyManifest,
922
+ BoardLike,
923
+ > = TypedOptionalArray<
924
+ TypedOptionalArray<
925
+ TypedOptionalArray<
926
+ TypedFields<
927
+ Omit<Entry, "spaces" | "relations" | "containers">,
928
+ EffectiveSchemaForEntry<Manifest, Entry, "boardFieldsSchema">,
929
+ Manifest,
930
+ BoardLike
931
+ >,
932
+ Entry,
933
+ "spaces",
934
+ TypedFields<
935
+ ArrayItem<
936
+ NonNullable<Entry extends { spaces?: infer Spaces } ? Spaces : never>
937
+ >,
938
+ EffectiveSchemaForEntry<Manifest, Entry, "spaceFieldsSchema">,
939
+ Manifest,
940
+ BoardLike
941
+ >
942
+ >,
943
+ Entry,
944
+ "relations",
945
+ TypedBoardRelation<
946
+ ArrayItem<
947
+ NonNullable<
948
+ Entry extends { relations?: infer Relations } ? Relations : never
949
+ >
950
+ >,
951
+ Manifest,
952
+ BoardLike,
953
+ EffectiveSchemaForEntry<Manifest, Entry, "relationFieldsSchema">
954
+ >
955
+ >,
956
+ Entry,
957
+ "containers",
958
+ TypedBoardContainer<
959
+ ArrayItem<
960
+ NonNullable<
961
+ Entry extends { containers?: infer Containers } ? Containers : never
962
+ >
963
+ >,
964
+ Manifest,
965
+ BoardLike,
966
+ EffectiveSchemaForEntry<Manifest, Entry, "containerFieldsSchema">
967
+ >
968
+ >;
969
+ type TypedHexBoardLike<
970
+ Entry,
971
+ Manifest extends GameTopologyManifest,
972
+ BoardLike,
973
+ > = TypedOptionalArray<
974
+ TypedOptionalArray<
975
+ TypedOptionalArray<
976
+ TypedFields<
977
+ Omit<Entry, "spaces" | "edges" | "vertices">,
978
+ EffectiveSchemaForEntry<Manifest, Entry, "boardFieldsSchema">,
979
+ Manifest,
980
+ BoardLike
981
+ >,
982
+ Entry,
983
+ "spaces",
984
+ TypedFields<
985
+ ArrayItem<
986
+ NonNullable<Entry extends { spaces?: infer Spaces } ? Spaces : never>
987
+ >,
988
+ EffectiveSchemaForEntry<Manifest, Entry, "spaceFieldsSchema">,
989
+ Manifest,
990
+ BoardLike
991
+ >
992
+ >,
993
+ Entry,
994
+ "edges",
995
+ TypedFields<
996
+ ArrayItem<
997
+ NonNullable<Entry extends { edges?: infer Edges } ? Edges : never>
998
+ >,
999
+ EffectiveSchemaForEntry<Manifest, Entry, "edgeFieldsSchema">,
1000
+ Manifest,
1001
+ BoardLike
1002
+ >
1003
+ >,
1004
+ Entry,
1005
+ "vertices",
1006
+ TypedFields<
1007
+ ArrayItem<
1008
+ NonNullable<
1009
+ Entry extends { vertices?: infer Vertices } ? Vertices : never
1010
+ >
1011
+ >,
1012
+ EffectiveSchemaForEntry<Manifest, Entry, "vertexFieldsSchema">,
1013
+ Manifest,
1014
+ BoardLike
1015
+ >
1016
+ >;
1017
+ type TypedSquareBoardLike<
1018
+ Entry,
1019
+ Manifest extends GameTopologyManifest,
1020
+ BoardLike,
1021
+ > = TypedOptionalArray<
1022
+ TypedOptionalArray<
1023
+ TypedOptionalArray<
1024
+ TypedOptionalArray<
1025
+ TypedOptionalArray<
1026
+ TypedFields<
1027
+ Omit<
1028
+ Entry,
1029
+ "spaces" | "relations" | "containers" | "edges" | "vertices"
1030
+ >,
1031
+ EffectiveSchemaForEntry<Manifest, Entry, "boardFieldsSchema">,
1032
+ Manifest,
1033
+ BoardLike
1034
+ >,
1035
+ Entry,
1036
+ "spaces",
1037
+ TypedFields<
1038
+ ArrayItem<
1039
+ NonNullable<
1040
+ Entry extends { spaces?: infer Spaces } ? Spaces : never
1041
+ >
1042
+ >,
1043
+ EffectiveSchemaForEntry<Manifest, Entry, "spaceFieldsSchema">,
1044
+ Manifest,
1045
+ BoardLike
1046
+ >
1047
+ >,
1048
+ Entry,
1049
+ "relations",
1050
+ TypedBoardRelation<
1051
+ ArrayItem<
1052
+ NonNullable<
1053
+ Entry extends { relations?: infer Relations } ? Relations : never
1054
+ >
1055
+ >,
1056
+ Manifest,
1057
+ BoardLike,
1058
+ EffectiveSchemaForEntry<Manifest, Entry, "relationFieldsSchema">
1059
+ >
1060
+ >,
1061
+ Entry,
1062
+ "containers",
1063
+ TypedBoardContainer<
1064
+ ArrayItem<
1065
+ NonNullable<
1066
+ Entry extends { containers?: infer Containers } ? Containers : never
1067
+ >
1068
+ >,
1069
+ Manifest,
1070
+ BoardLike,
1071
+ EffectiveSchemaForEntry<Manifest, Entry, "containerFieldsSchema">
1072
+ >
1073
+ >,
1074
+ Entry,
1075
+ "edges",
1076
+ TypedFields<
1077
+ ArrayItem<
1078
+ NonNullable<Entry extends { edges?: infer Edges } ? Edges : never>
1079
+ >,
1080
+ EffectiveSchemaForEntry<Manifest, Entry, "edgeFieldsSchema">,
1081
+ Manifest,
1082
+ BoardLike
1083
+ >
1084
+ >,
1085
+ Entry,
1086
+ "vertices",
1087
+ TypedFields<
1088
+ ArrayItem<
1089
+ NonNullable<
1090
+ Entry extends { vertices?: infer Vertices } ? Vertices : never
1091
+ >
1092
+ >,
1093
+ EffectiveSchemaForEntry<Manifest, Entry, "vertexFieldsSchema">,
1094
+ Manifest,
1095
+ BoardLike
1096
+ >
1097
+ >;
1098
+ type TypedBoardLikeEntry<
1099
+ Entry,
1100
+ Manifest extends GameTopologyManifest,
1101
+ > = Entry extends { layout: "generic" }
1102
+ ? TypedGenericBoardLike<Entry, Manifest, BoardLikeForEntry<Manifest, Entry>>
1103
+ : Entry extends { layout: "hex" }
1104
+ ? TypedHexBoardLike<Entry, Manifest, BoardLikeForEntry<Manifest, Entry>>
1105
+ : Entry extends { layout: "square" }
1106
+ ? TypedSquareBoardLike<
1107
+ Entry,
1108
+ Manifest,
1109
+ BoardLikeForEntry<Manifest, Entry>
1110
+ >
1111
+ : Entry;
1112
+
1113
+ type TypedCard<
1114
+ Card,
1115
+ Manifest extends GameTopologyManifest,
1116
+ CardSchema,
1117
+ > = Card extends { type: infer CardType extends string }
1118
+ ? Omit<TypedVisibility<Card, Manifest>, "home" | "properties"> & {
1119
+ home?: TypedComponentHomeSpec<Manifest>;
1120
+ properties: CardSchema extends {
1121
+ variants: infer Variants extends Record<string, unknown>;
1122
+ shared?: infer Shared;
1123
+ }
1124
+ ? CardType extends keyof Variants
1125
+ ? SchemaValueForObjectSchema<
1126
+ MergeSharedProperties<Variants[CardType], Shared>,
1127
+ Manifest
1128
+ >
1129
+ : never
1130
+ : SchemaValueForObjectSchema<CardSchema, Manifest>;
1131
+ }
1132
+ : Card;
1133
+
1134
+ type TypedCardSet<
1135
+ CardSet,
1136
+ Manifest extends GameTopologyManifest,
1137
+ > = CardSet extends {
1138
+ type: "manual";
1139
+ cardSchema: infer CardSchema;
1140
+ cards: infer Cards extends readonly unknown[];
1141
+ }
1142
+ ? Omit<CardSet, "cards"> & {
1143
+ cards: ReadonlyArray<TypedCard<ArrayItem<Cards>, Manifest, CardSchema>>;
1144
+ }
1145
+ : CardSet;
1146
+
1147
+ type TypedAllowedCardSetIds<
1148
+ T,
1149
+ Manifest extends GameTopologyManifest,
1150
+ > = T extends object
1151
+ ? Omit<T, "allowedCardSetIds"> & {
1152
+ allowedCardSetIds?: readonly CardSetId<Manifest>[];
1153
+ }
1154
+ : T;
1155
+
1156
+ type TypedZone<
1157
+ Zone,
1158
+ Manifest extends GameTopologyManifest,
1159
+ > = TypedAllowedCardSetIds<Zone, Manifest>;
1160
+
1161
+ type TypedPieceSeed<
1162
+ Seed,
1163
+ Manifest extends GameTopologyManifest,
1164
+ > = Seed extends { typeId: infer CurrentTypeId }
1165
+ ? CurrentTypeId extends PieceTypeId<Manifest>
1166
+ ? Omit<
1167
+ TypedSeedLocationSpec<TypedVisibility<Seed, Manifest>, Manifest>,
1168
+ "typeId" | "ownerId" | "home" | "fields"
1169
+ > & {
1170
+ typeId: CurrentTypeId;
1171
+ fields?: SchemaValueForObjectSchema<
1172
+ PieceTypeOf<Manifest, CurrentTypeId> extends {
1173
+ fieldsSchema?: infer FieldsSchema;
1174
+ }
1175
+ ? FieldsSchema
1176
+ : undefined,
1177
+ Manifest
1178
+ >;
1179
+ } & Pick<
1180
+ TypedSeedLocationSpec<TypedVisibility<Seed, Manifest>, Manifest>,
1181
+ "ownerId" | "home"
1182
+ >
1183
+ : Omit<Seed, "typeId"> & {
1184
+ typeId: PieceTypeId<Manifest>;
1185
+ }
1186
+ : never;
1187
+
1188
+ type TypedDieSeed<Seed, Manifest extends GameTopologyManifest> = Seed extends {
1189
+ typeId: infer CurrentTypeId;
1190
+ }
1191
+ ? CurrentTypeId extends DieTypeId<Manifest>
1192
+ ? Omit<
1193
+ TypedSeedLocationSpec<TypedVisibility<Seed, Manifest>, Manifest>,
1194
+ "typeId" | "ownerId" | "home" | "fields"
1195
+ > & {
1196
+ typeId: CurrentTypeId;
1197
+ fields?: SchemaValueForObjectSchema<
1198
+ DieTypeOf<Manifest, CurrentTypeId> extends {
1199
+ fieldsSchema?: infer FieldsSchema;
1200
+ }
1201
+ ? FieldsSchema
1202
+ : undefined,
1203
+ Manifest
1204
+ >;
1205
+ } & Pick<
1206
+ TypedSeedLocationSpec<TypedVisibility<Seed, Manifest>, Manifest>,
1207
+ "ownerId" | "home"
1208
+ >
1209
+ : Omit<Seed, "typeId"> & {
1210
+ typeId: DieTypeId<Manifest>;
1211
+ }
1212
+ : never;
1213
+
1214
+ type TypedSetupOptionValues<Manifest extends GameTopologyManifest> = Partial<{
1215
+ [OptionId in SetupOptionId<Manifest>]: SetupOptionChoiceIdFor<
1216
+ Manifest,
1217
+ OptionId
1218
+ >;
1219
+ }>;
1220
+
1221
+ type TypedSetupProfile<
1222
+ Profile,
1223
+ Manifest extends GameTopologyManifest,
1224
+ > = Profile extends object
1225
+ ? Omit<Profile, "optionValues"> & {
1226
+ optionValues?: TypedSetupOptionValues<Manifest>;
1227
+ }
1228
+ : Profile;
1229
+
1230
+ export type TypedTopologyManifest<Manifest extends GameTopologyManifest> = Omit<
1231
+ Manifest,
1232
+ | "cardSets"
1233
+ | "zones"
1234
+ | "boardTemplates"
1235
+ | "boards"
1236
+ | "pieceSeeds"
1237
+ | "dieSeeds"
1238
+ | "setupProfiles"
1239
+ > & {
1240
+ cardSets: ReadonlyArray<
1241
+ TypedCardSet<ArrayItem<Manifest["cardSets"]>, Manifest>
1242
+ >;
1243
+ zones?: Manifest["zones"] extends readonly unknown[]
1244
+ ? ReadonlyArray<TypedZone<ArrayItem<Manifest["zones"]>, Manifest>>
1245
+ : Manifest["zones"];
1246
+ boardTemplates?: Manifest["boardTemplates"] extends readonly unknown[]
1247
+ ? ReadonlyArray<
1248
+ TypedBoardLikeEntry<ArrayItem<Manifest["boardTemplates"]>, Manifest>
1249
+ >
1250
+ : Manifest["boardTemplates"];
1251
+ boards: Manifest["boards"] extends readonly unknown[]
1252
+ ? ReadonlyArray<
1253
+ TypedBoardLikeEntry<ArrayItem<Manifest["boards"]>, Manifest>
1254
+ >
1255
+ : Manifest["boards"];
1256
+ pieceSeeds?: Manifest["pieceSeeds"] extends readonly unknown[]
1257
+ ? ReadonlyArray<TypedPieceSeed<ArrayItem<Manifest["pieceSeeds"]>, Manifest>>
1258
+ : Manifest["pieceSeeds"];
1259
+ dieSeeds?: Manifest["dieSeeds"] extends readonly unknown[]
1260
+ ? ReadonlyArray<TypedDieSeed<ArrayItem<Manifest["dieSeeds"]>, Manifest>>
1261
+ : Manifest["dieSeeds"];
1262
+ setupProfiles?: Manifest["setupProfiles"] extends readonly unknown[]
1263
+ ? ReadonlyArray<
1264
+ TypedSetupProfile<ArrayItem<Manifest["setupProfiles"]>, Manifest>
1265
+ >
1266
+ : Manifest["setupProfiles"];
1267
+ };
1268
+
1269
+ type TopologyManifestValidation<Manifest> =
1270
+ Manifest extends GameTopologyManifest
1271
+ ? TypedTopologyManifest<Manifest>
1272
+ : GameTopologyManifest;
1273
+
1274
+ type DefinedTopologyManifest<Manifest> = Manifest extends GameTopologyManifest
1275
+ ? Manifest
1276
+ : GameTopologyManifest;
1277
+
1278
+ export function defineTopologyManifest<const Manifest>(
1279
+ manifest: Manifest & TopologyManifestValidation<NoInfer<Manifest>>,
1280
+ ): DefinedTopologyManifest<Manifest> {
1281
+ return manifest as DefinedTopologyManifest<Manifest>;
1282
+ }