@dreamboard-games/sdk 0.2.1-alpha.1 → 0.3.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{HandView-ncJIVLhN.d.ts → HandView-PYDmehVD.d.ts} +1 -1
- package/dist/{ResourceCounter-CTREyF73.d.ts → ResourceCounter-BTXklCEZ.d.ts} +1 -1
- package/dist/{ThemeProvider-BBMVT3KG.d.ts → ThemeProvider-DvMl17Ny.d.ts} +1 -1
- package/dist/{chunk-NKCRKGR2.js → chunk-3RQEICD3.js} +2 -2
- package/dist/{chunk-ZABVH7AO.js → chunk-ADYH6PVT.js} +1336 -1363
- package/dist/chunk-ADYH6PVT.js.map +1 -0
- package/dist/{chunk-PEI3FIL2.js → chunk-P7VMTJ5D.js} +2 -2
- package/dist/{chunk-PEI3FIL2.js.map → chunk-P7VMTJ5D.js.map} +1 -1
- package/dist/{chunk-WG4JQL3S.js → chunk-QZ6X4B5P.js} +1177 -1109
- package/dist/chunk-QZ6X4B5P.js.map +1 -0
- package/dist/{chunk-MZNVHMJ5.js → chunk-TXXLS3OI.js} +405 -309
- package/dist/chunk-TXXLS3OI.js.map +1 -0
- package/dist/{chunk-FDNZTDD6.js → chunk-W6SGFWXH.js} +48 -44
- package/dist/chunk-W6SGFWXH.js.map +1 -0
- package/dist/{chunk-MKXPVOUT.js → chunk-Y2AFYBMB.js} +48 -4
- package/dist/chunk-Y2AFYBMB.js.map +1 -0
- package/dist/{index-BwqPQtBu.d.ts → codegen.d.ts} +57 -565
- package/dist/{infrastructure/workspace-codegen.js → codegen.js} +3 -3
- package/dist/{components-BoiVSYqx.d.ts → components-DaIqi9QM.d.ts} +48 -37
- package/dist/{hex-board-view-1iAyJRFn.d.ts → hex-board-view-UCUjMALd.d.ts} +2 -2
- package/dist/{infrastructure/reducer-bundle-abi.d.ts → index.d-BGqVifr_.d.ts} +289 -10
- package/dist/index.js +1 -1
- package/dist/package-set.d.ts +2 -2
- package/dist/package-set.js +1 -1
- package/dist/primitive-props-BNHDkgd7.d.ts +16 -0
- package/dist/reducer-contract.d.ts +3 -0
- package/dist/{infrastructure/reducer-bundle-abi.js → reducer-contract.js} +4 -4
- package/dist/reducer.d.ts +185 -179
- package/dist/reducer.js +1363 -1372
- package/dist/reducer.js.map +1 -1
- package/dist/runtime/primitives.d.ts +9 -9
- package/dist/runtime/primitives.js +7 -7
- package/dist/runtime/runtime-api.d.ts +2 -0
- package/dist/runtime/runtime-api.js +1 -0
- package/dist/runtime/workspace-contract.d.ts +62 -17
- package/dist/runtime/workspace-contract.js +5 -6
- package/dist/{runtime-api-CPLm_XDG.d.ts → runtime-api-tGL3ArsB.d.ts} +103 -4
- package/dist/runtime.d.ts +11 -57
- package/dist/runtime.js +487 -8
- package/dist/runtime.js.map +1 -1
- package/dist/testing.d.ts +4 -4
- package/dist/testing.js.map +1 -1
- package/dist/types.d.ts +1531 -85
- package/dist/types.js +1 -3
- package/dist/types.js.map +1 -1
- package/dist/ui/components.d.ts +7 -8
- package/dist/ui/components.js +1 -1
- package/dist/ui/defaults.d.ts +1 -1
- package/dist/ui/{types/player-state.d.ts → player-state.d.ts} +2 -2
- package/dist/{ui-contract-rzKBwOLC.d.ts → ui-contract-SctM4ibF.d.ts} +155 -150
- package/dist/ui.d.ts +10 -11
- package/dist/ui.js +2 -2
- package/package.json +30 -75
- package/dist/bundle-CDd5FKeD.d.ts +0 -283
- package/dist/cards-Sl3b40Mv.d.ts +0 -13
- package/dist/chunk-326PGVAA.js +0 -34
- package/dist/chunk-326PGVAA.js.map +0 -1
- package/dist/chunk-FDNZTDD6.js.map +0 -1
- package/dist/chunk-I46YJSOD.js +0 -1
- package/dist/chunk-MKXPVOUT.js.map +0 -1
- package/dist/chunk-MZNVHMJ5.js.map +0 -1
- package/dist/chunk-T52J5RMF.js +0 -1
- package/dist/chunk-WG4JQL3S.js.map +0 -1
- package/dist/chunk-XV6D3ET4.js +0 -485
- package/dist/chunk-XV6D3ET4.js.map +0 -1
- package/dist/chunk-ZABVH7AO.js.map +0 -1
- package/dist/generated/runtime/primitives.d.ts +0 -13
- package/dist/generated/runtime/primitives.js +0 -181
- package/dist/generated/runtime/primitives.js.map +0 -1
- package/dist/generated/runtime-api.d.ts +0 -3
- package/dist/generated/runtime-api.js +0 -2
- package/dist/generated/runtime.d.ts +0 -15
- package/dist/generated/runtime.js +0 -19
- package/dist/generated/runtime.js.map +0 -1
- package/dist/generated/workspace-contract.d.ts +0 -15
- package/dist/generated/workspace-contract.js +0 -15
- package/dist/generated/workspace-contract.js.map +0 -1
- package/dist/infrastructure/reducer-bundle-abi.js.map +0 -1
- package/dist/infrastructure/workspace-codegen.d.ts +0 -53
- package/dist/infrastructure/workspace-codegen.js.map +0 -1
- package/dist/manifest-contract-BNHVGFtU.d.ts +0 -9
- package/dist/primitive-props-DpKs-GCr.d.ts +0 -11
- package/dist/runtime/types/runtime-api.d.ts +0 -1
- package/dist/runtime/types/runtime-api.js +0 -2
- package/dist/runtime/types/runtime-api.js.map +0 -1
- package/dist/runtime-api-3dshj6kK.d.ts +0 -101
- package/dist/slots-1GPGihk8.d.ts +0 -8
- package/src/browser-interaction/attributes.ts +0 -211
- package/src/browser-interaction/canonical.ts +0 -77
- package/src/browser-interaction/constants.ts +0 -77
- package/src/browser-interaction/effects.ts +0 -176
- package/src/browser-interaction/index.ts +0 -111
- package/src/browser-interaction/normalize.ts +0 -997
- package/src/browser-interaction/registry.ts +0 -70
- package/src/browser-interaction/resolve.ts +0 -596
- package/src/browser-interaction/schemas.ts +0 -152
- package/src/browser-interaction/types.ts +0 -304
- package/src/browser-interaction.ts +0 -1
- package/src/generated/reducer-contract/builders.ts +0 -90
- package/src/generated/reducer-contract/version.ts +0 -9
- package/src/generated/reducer-contract/wire.ts +0 -100
- package/src/generated/reducer-contract/zod.ts +0 -103
- package/src/generated/runtime/primitives.ts +0 -2
- package/src/generated/runtime-api.ts +0 -5
- package/src/generated/runtime.ts +0 -35
- package/src/generated/workspace-contract.ts +0 -2
- package/src/index.ts +0 -7
- package/src/infrastructure/reducer-bundle-abi.ts +0 -8
- package/src/infrastructure/reducer-contract/bundle.ts +0 -37
- package/src/infrastructure/workspace-codegen/hex-geometry.ts +0 -69
- package/src/infrastructure/workspace-codegen/index.ts +0 -64
- package/src/infrastructure/workspace-codegen/manifest-contract.ts +0 -6632
- package/src/infrastructure/workspace-codegen/manifest-validation.ts +0 -795
- package/src/infrastructure/workspace-codegen/ownership.ts +0 -131
- package/src/infrastructure/workspace-codegen/preset-card-sets.ts +0 -169
- package/src/infrastructure/workspace-codegen/seeds.ts +0 -1705
- package/src/infrastructure/workspace-codegen.ts +0 -1
- package/src/package-set.ts +0 -19
- package/src/reducer/authoring/contract.ts +0 -157
- package/src/reducer/authoring/effect.ts +0 -224
- package/src/reducer/authoring/game.ts +0 -23
- package/src/reducer/authoring/interaction.ts +0 -98
- package/src/reducer/authoring/phase.ts +0 -300
- package/src/reducer/authoring/types.ts +0 -70
- package/src/reducer/authoring/validation.ts +0 -382
- package/src/reducer/authoring/view-stage.ts +0 -68
- package/src/reducer/authoring.ts +0 -29
- package/src/reducer/bundle/ingress-bundle.ts +0 -491
- package/src/reducer/bundle/trusted/engine-instruction-resolver.ts +0 -254
- package/src/reducer/bundle/trusted/flow-instruction-resolver.ts +0 -73
- package/src/reducer/bundle/trusted/instruction-runner.ts +0 -414
- package/src/reducer/bundle/trusted/interaction-authorization.ts +0 -137
- package/src/reducer/bundle/trusted/interaction-collectors.ts +0 -859
- package/src/reducer/bundle/trusted/interaction-decision.ts +0 -747
- package/src/reducer/bundle/trusted/interaction-resolver.ts +0 -95
- package/src/reducer/bundle/trusted/interaction-types.ts +0 -174
- package/src/reducer/bundle/trusted/lifecycle-runner.ts +0 -427
- package/src/reducer/bundle/trusted/projection-builder.ts +0 -680
- package/src/reducer/bundle/trusted/projection-context.ts +0 -39
- package/src/reducer/bundle/trusted/rng-sampler.ts +0 -150
- package/src/reducer/bundle/trusted/runtime-registry.ts +0 -120
- package/src/reducer/bundle/trusted/runtime-scope.ts +0 -336
- package/src/reducer/bundle/trusted/simultaneous-player.ts +0 -97
- package/src/reducer/bundle/trusted/stage-resolver.ts +0 -87
- package/src/reducer/bundle/trusted/static-projection.ts +0 -116
- package/src/reducer/bundle/trusted/trusted-runtime-args.ts +0 -97
- package/src/reducer/bundle/trusted/trusted-runtime-result.ts +0 -39
- package/src/reducer/bundle/trusted/trusted-setup-profiles.ts +0 -43
- package/src/reducer/bundle/trusted/trusted-state-codec.ts +0 -48
- package/src/reducer/bundle/trusted-bundle.ts +0 -97
- package/src/reducer/bundle/types.ts +0 -171
- package/src/reducer/bundle.ts +0 -2
- package/src/reducer/client-param-schemas.ts +0 -57
- package/src/reducer/compose.ts +0 -34
- package/src/reducer/core/runtime-input.ts +0 -30
- package/src/reducer/core/runtime-instruction.ts +0 -59
- package/src/reducer/core/types.ts +0 -62
- package/src/reducer/definition-index.ts +0 -277
- package/src/reducer/derived.ts +0 -106
- package/src/reducer/effects.ts +0 -92
- package/src/reducer/engine/runtime-instruction-engine.ts +0 -155
- package/src/reducer/ingress/decode-runtime-input.ts +0 -7
- package/src/reducer/ingress/decode-session-state.ts +0 -9
- package/src/reducer/ingress/encode-session-state.ts +0 -6
- package/src/reducer/ingress/input-codec.ts +0 -18
- package/src/reducer/ingress/phase-schemas.ts +0 -62
- package/src/reducer/ingress/raw-types.ts +0 -107
- package/src/reducer/ingress/runtime-codec.ts +0 -14
- package/src/reducer/ingress/runtime-payload.ts +0 -13
- package/src/reducer/ingress/session-codec.ts +0 -392
- package/src/reducer/ingress/types.ts +0 -6
- package/src/reducer/inputs/boardInput.ts +0 -217
- package/src/reducer/inputs/boardTarget.ts +0 -190
- package/src/reducer/inputs/cardInput.ts +0 -86
- package/src/reducer/inputs/cardTarget.ts +0 -101
- package/src/reducer/inputs/choiceTarget.ts +0 -104
- package/src/reducer/inputs/defineInputs.ts +0 -71
- package/src/reducer/inputs/formInput.ts +0 -809
- package/src/reducer/inputs/many.ts +0 -120
- package/src/reducer/inputs/promptInput.ts +0 -87
- package/src/reducer/inputs/rngInput.ts +0 -58
- package/src/reducer/inputs/targetRule.ts +0 -123
- package/src/reducer/inputs.ts +0 -41
- package/src/reducer/model/definition.ts +0 -1072
- package/src/reducer/model/extract.ts +0 -745
- package/src/reducer/model/manifest.ts +0 -570
- package/src/reducer/model/queries.ts +0 -641
- package/src/reducer/model/runtime.ts +0 -264
- package/src/reducer/model/spec.ts +0 -1386
- package/src/reducer/model/table.ts +0 -260
- package/src/reducer/model.ts +0 -7
- package/src/reducer/ops.ts +0 -1034
- package/src/reducer/parse-utils.ts +0 -28
- package/src/reducer/per-player.ts +0 -422
- package/src/reducer/rng.ts +0 -69
- package/src/reducer/schema-helpers.ts +0 -185
- package/src/reducer/setup-bootstrap-helpers.ts +0 -171
- package/src/reducer/setup-bootstrap.ts +0 -481
- package/src/reducer/table-ops.ts +0 -2671
- package/src/reducer/table-queries.ts +0 -372
- package/src/reducer/transaction.ts +0 -120
- package/src/reducer.ts +0 -314
- package/src/runtime/primitives.ts +0 -1
- package/src/runtime/types/runtime-api.ts +0 -1
- package/src/runtime/workspace-contract.ts +0 -32
- package/src/runtime-internal/components/InteractionForm.tsx +0 -1647
- package/src/runtime-internal/components/PluginRuntime.tsx +0 -105
- package/src/runtime-internal/components/board/target-layer.ts +0 -72
- package/src/runtime-internal/context/ClientParamSchemaContext.tsx +0 -44
- package/src/runtime-internal/context/InteractionDraftContext.tsx +0 -279
- package/src/runtime-internal/context/PluginSessionContext.tsx +0 -47
- package/src/runtime-internal/context/PluginStateContext.tsx +0 -303
- package/src/runtime-internal/context/RuntimeContext.tsx +0 -96
- package/src/runtime-internal/defaults/components.tsx +0 -409
- package/src/runtime-internal/defaults/index.ts +0 -11
- package/src/runtime-internal/errors/ValidationError.ts +0 -29
- package/src/runtime-internal/hooks/useActivePlayers.ts +0 -33
- package/src/runtime-internal/hooks/useBoardInteractions.ts +0 -727
- package/src/runtime-internal/hooks/useGameSelector.ts +0 -105
- package/src/runtime-internal/hooks/useGameView.ts +0 -9
- package/src/runtime-internal/hooks/useInteractionByKey.ts +0 -354
- package/src/runtime-internal/hooks/useInteractionHandle.ts +0 -438
- package/src/runtime-internal/hooks/useIsMyTurn.ts +0 -20
- package/src/runtime-internal/hooks/useLobby.ts +0 -76
- package/src/runtime-internal/hooks/useMe.ts +0 -48
- package/src/runtime-internal/hooks/usePlayerInfo.ts +0 -28
- package/src/runtime-internal/hooks/usePlayerTurnOrder.ts +0 -23
- package/src/runtime-internal/hooks/usePluginRuntime.ts +0 -147
- package/src/runtime-internal/hooks/useSeatInbox.ts +0 -61
- package/src/runtime-internal/hooks/useSimultaneousPhase.ts +0 -10
- package/src/runtime-internal/index.ts +0 -42
- package/src/runtime-internal/internal.ts +0 -43
- package/src/runtime-internal/plugin-styles.css +0 -250
- package/src/runtime-internal/primitives/board.tsx +0 -530
- package/src/runtime-internal/primitives/dialog-lifecycle.ts +0 -58
- package/src/runtime-internal/primitives/dice.tsx +0 -79
- package/src/runtime-internal/primitives/game-ui-provider.tsx +0 -35
- package/src/runtime-internal/primitives/game.tsx +0 -387
- package/src/runtime-internal/primitives/hand-intent-adapter.ts +0 -147
- package/src/runtime-internal/primitives/hand-surface.tsx +0 -594
- package/src/runtime-internal/primitives/index.ts +0 -196
- package/src/runtime-internal/primitives/interaction-form-binding.tsx +0 -56
- package/src/runtime-internal/primitives/interaction-submit.ts +0 -90
- package/src/runtime-internal/primitives/interaction.tsx +0 -1146
- package/src/runtime-internal/primitives/phase.tsx +0 -43
- package/src/runtime-internal/primitives/player-roster.tsx +0 -302
- package/src/runtime-internal/primitives/primitive-props.tsx +0 -101
- package/src/runtime-internal/primitives/prompt.tsx +0 -255
- package/src/runtime-internal/primitives/ui.tsx +0 -60
- package/src/runtime-internal/primitives/zone.tsx +0 -791
- package/src/runtime-internal/reducer.ts +0 -30
- package/src/runtime-internal/runtime/createPluginRuntimeAPI.ts +0 -605
- package/src/runtime-internal/types/plugin-state.ts +0 -514
- package/src/runtime-internal/types/reducer-state.ts +0 -24
- package/src/runtime-internal/types/runtime-api.ts +0 -114
- package/src/runtime-internal/ui-contract.ts +0 -519
- package/src/runtime-internal/utils/browser-interaction-effects.ts +0 -240
- package/src/runtime-internal/utils/card-intent-adapter.ts +0 -546
- package/src/runtime-internal/utils/interaction-draft-digest.ts +0 -252
- package/src/runtime-internal/utils/interaction-inputs.ts +0 -492
- package/src/runtime-internal/utils/interaction-labels.ts +0 -23
- package/src/runtime-internal/utils/interaction-router.ts +0 -273
- package/src/runtime-internal/utils/interaction-status.ts +0 -74
- package/src/runtime-internal/utils/semantic-projection-digest.ts +0 -407
- package/src/runtime-internal/workspace-contract.ts +0 -1170
- package/src/runtime.ts +0 -34
- package/src/testing/create-expect-api.ts +0 -352
- package/src/testing/create-test-runtime.ts +0 -381
- package/src/testing/definitions.ts +0 -127
- package/src/testing/index.ts +0 -3
- package/src/testing.ts +0 -1
- package/src/type-stubs/manifest-contract.d.ts +0 -42
- package/src/type-stubs/manifest-contract.js +0 -72
- package/src/type-stubs/ui-contract.d.ts +0 -5
- package/src/type-stubs/ui-contract.js +0 -1
- package/src/types/authoring-card-properties.type-test.ts +0 -266
- package/src/types/authoring.ts +0 -1282
- package/src/types/cards.ts +0 -19
- package/src/types/contracts.ts +0 -1550
- package/src/types/generated-helpers.ts +0 -35
- package/src/types/index.ts +0 -147
- package/src/types/slots.ts +0 -11
- package/src/types.ts +0 -1
- package/src/ui/components/ActionButton.tsx +0 -97
- package/src/ui/components/ActionPanel.tsx +0 -315
- package/src/ui/components/Card.tsx +0 -378
- package/src/ui/components/CardDragSurface.tsx +0 -1076
- package/src/ui/components/ChromeSuppressionContext.tsx +0 -70
- package/src/ui/components/CostDisplay.tsx +0 -145
- package/src/ui/components/DiceRoller.tsx +0 -581
- package/src/ui/components/Drawer.tsx +0 -180
- package/src/ui/components/ErrorBoundary.tsx +0 -275
- package/src/ui/components/GameEndDisplay.tsx +0 -398
- package/src/ui/components/GameSkeleton.tsx +0 -260
- package/src/ui/components/Hand.tsx +0 -468
- package/src/ui/components/HandDock.tsx +0 -299
- package/src/ui/components/HandView.tsx +0 -441
- package/src/ui/components/MobileHandTray.tsx +0 -381
- package/src/ui/components/MoreActions.tsx +0 -143
- package/src/ui/components/PhaseIndicator.tsx +0 -341
- package/src/ui/components/PlayArea.tsx +0 -146
- package/src/ui/components/PrimaryActionButton.tsx +0 -336
- package/src/ui/components/PrimaryButton.tsx +0 -45
- package/src/ui/components/ResourceCounter.tsx +0 -270
- package/src/ui/components/StagingZone.tsx +0 -134
- package/src/ui/components/ThemedButton.tsx +0 -113
- package/src/ui/components/Toast.tsx +0 -264
- package/src/ui/components/board/HexGrid.tsx +0 -1297
- package/src/ui/components/board/NetworkGraph.tsx +0 -476
- package/src/ui/components/board/SlotSystem.tsx +0 -388
- package/src/ui/components/board/SquareGrid.tsx +0 -1165
- package/src/ui/components/board/TrackBoard.tsx +0 -496
- package/src/ui/components/board/ZoneMap.tsx +0 -448
- package/src/ui/components/board/hex-board-view.ts +0 -123
- package/src/ui/components/board/index.ts +0 -142
- package/src/ui/components/board/interaction-accessibility.ts +0 -21
- package/src/ui/components/board/target-layer.ts +0 -67
- package/src/ui/components/card-render-content.type-test.ts +0 -27
- package/src/ui/components/hand-layout-math.ts +0 -163
- package/src/ui/components/hand-pointer-engine.ts +0 -413
- package/src/ui/components/index.ts +0 -245
- package/src/ui/components.ts +0 -1
- package/src/ui/defaults/components.tsx +0 -106
- package/src/ui/defaults/index.ts +0 -8
- package/src/ui/defaults.ts +0 -1
- package/src/ui/errors/ValidationError.ts +0 -29
- package/src/ui/helpers/cards.ts +0 -19
- package/src/ui/helpers/track-board.ts +0 -211
- package/src/ui/hooks/useBoardTopology.ts +0 -316
- package/src/ui/hooks/useCards.ts +0 -10
- package/src/ui/hooks/useHandCardPointer.ts +0 -381
- package/src/ui/hooks/useHandLayout.ts +0 -378
- package/src/ui/hooks/useHandPresentation.ts +0 -121
- package/src/ui/hooks/useHexBoard.ts +0 -74
- package/src/ui/hooks/useHexGrid.ts +0 -185
- package/src/ui/hooks/useIsMobile.ts +0 -35
- package/src/ui/hooks/usePanZoom.ts +0 -278
- package/src/ui/hooks/useSquareBoard.ts +0 -124
- package/src/ui/hooks/useSquareGrid.ts +0 -328
- package/src/ui/index.ts +0 -98
- package/src/ui/internal/ui/alert.tsx +0 -51
- package/src/ui/internal/ui/button.tsx +0 -58
- package/src/ui/internal/ui/dialog.tsx +0 -134
- package/src/ui/internal/ui/input.tsx +0 -21
- package/src/ui/internal/ui/label.tsx +0 -21
- package/src/ui/internal/ui/select.tsx +0 -129
- package/src/ui/internal/ui/tooltip.tsx +0 -54
- package/src/ui/internal/ui/utils.ts +0 -5
- package/src/ui/plugin-styles.css +0 -250
- package/src/ui/primitives/dialog-lifecycle.ts +0 -58
- package/src/ui/primitives/dice.tsx +0 -79
- package/src/ui/primitives/primitive-props.tsx +0 -101
- package/src/ui/theme/ThemeProvider.tsx +0 -252
- package/src/ui/theme/board.ts +0 -61
- package/src/ui/theme/css-vars.ts +0 -105
- package/src/ui/theme/derive.ts +0 -240
- package/src/ui/theme/index.ts +0 -61
- package/src/ui/theme/presets/arcade.ts +0 -261
- package/src/ui/theme/presets/studio.ts +0 -261
- package/src/ui/theme/presets/tabletop.ts +0 -266
- package/src/ui/theme/tokens.ts +0 -392
- package/src/ui/types/hex-color.ts +0 -20
- package/src/ui/types/player-state.ts +0 -463
- package/src/ui/types/tiled-board.ts +0 -785
- package/src/ui/types/visual-state.ts +0 -137
- package/src/ui.ts +0 -1
- /package/dist/{chunk-NKCRKGR2.js.map → chunk-3RQEICD3.js.map} +0 -0
- /package/dist/{chunk-I46YJSOD.js.map → codegen.js.map} +0 -0
- /package/dist/{chunk-T52J5RMF.js.map → reducer-contract.js.map} +0 -0
- /package/dist/{generated → runtime}/runtime-api.js.map +0 -0
- /package/dist/ui/{types/player-state.js → player-state.js} +0 -0
- /package/dist/ui/{types/player-state.js.map → player-state.js.map} +0 -0
package/dist/reducer.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
REDUCER_CONTRACT_VERSION,
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
builders_exports,
|
|
4
|
+
zod_exports
|
|
5
|
+
} from "./chunk-Y2AFYBMB.js";
|
|
5
6
|
import "./chunk-PZ5AY32C.js";
|
|
6
7
|
|
|
7
8
|
// src/reducer/model/manifest.ts
|
|
@@ -1748,7 +1749,7 @@ function createRuntimeInstructionEngine({
|
|
|
1748
1749
|
};
|
|
1749
1750
|
}
|
|
1750
1751
|
|
|
1751
|
-
// src/reducer/table
|
|
1752
|
+
// src/reducer/table/internal.ts
|
|
1752
1753
|
function ppRead(value, playerId) {
|
|
1753
1754
|
if (value === void 0) return void 0;
|
|
1754
1755
|
return perPlayerGet(value, playerId);
|
|
@@ -1768,9 +1769,6 @@ function orderedComponentIdsForLocation(table, predicate) {
|
|
|
1768
1769
|
(left, right) => locationPosition(left[1]) - locationPosition(right[1])
|
|
1769
1770
|
).map(([componentId]) => componentId);
|
|
1770
1771
|
}
|
|
1771
|
-
function allowedCardSetIdsForZone(table, zoneId) {
|
|
1772
|
-
return table.zones.cardSetIdsByZoneId?.[zoneId] ?? [];
|
|
1773
|
-
}
|
|
1774
1772
|
function hasOwnKey(record, key) {
|
|
1775
1773
|
return Object.prototype.hasOwnProperty.call(record, key);
|
|
1776
1774
|
}
|
|
@@ -1803,51 +1801,24 @@ function assertZoneScope(table, zoneId, expectedScope, operation, argumentName)
|
|
|
1803
1801
|
`Zone '${zoneId}' has scope '${actualScope}', but ${operation} requires ${argumentName} to be a ${expectedScope === "shared" ? "shared" : "perPlayer"} zone.`
|
|
1804
1802
|
);
|
|
1805
1803
|
}
|
|
1806
|
-
function
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
if (piece) {
|
|
1812
|
-
return piece.ownerId ?? null;
|
|
1813
|
-
}
|
|
1814
|
-
const die = table.dice[componentId];
|
|
1815
|
-
if (die) {
|
|
1816
|
-
return die.ownerId ?? null;
|
|
1817
|
-
}
|
|
1818
|
-
const owner = table.ownerOfCard[componentId];
|
|
1819
|
-
if (owner !== void 0) {
|
|
1820
|
-
return owner ?? null;
|
|
1821
|
-
}
|
|
1822
|
-
return null;
|
|
1823
|
-
}
|
|
1824
|
-
function componentData(table, componentId) {
|
|
1825
|
-
const piece = table.pieces[componentId];
|
|
1826
|
-
if (piece) {
|
|
1827
|
-
return piece.properties;
|
|
1828
|
-
}
|
|
1829
|
-
const die = table.dice[componentId];
|
|
1830
|
-
if (die) {
|
|
1831
|
-
return die.properties;
|
|
1832
|
-
}
|
|
1833
|
-
const card = table.cards[componentId];
|
|
1834
|
-
if (card) {
|
|
1835
|
-
return card.properties;
|
|
1836
|
-
}
|
|
1837
|
-
return void 0;
|
|
1804
|
+
function syncSharedZoneWithDeck(table, zoneId, nextCards) {
|
|
1805
|
+
table.decks[zoneId] = [...nextCards];
|
|
1806
|
+
table.zones.shared[zoneId] = [
|
|
1807
|
+
...nextCards
|
|
1808
|
+
];
|
|
1838
1809
|
}
|
|
1839
|
-
function
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
);
|
|
1849
|
-
}
|
|
1810
|
+
function syncPlayerZoneWithHand(table, zoneId, playerId, nextCards) {
|
|
1811
|
+
table.hands[zoneId] = ppWrite(table.hands[zoneId], playerId, [
|
|
1812
|
+
...nextCards
|
|
1813
|
+
]);
|
|
1814
|
+
table.zones.perPlayer[zoneId] = ppWrite(
|
|
1815
|
+
table.zones.perPlayer[zoneId],
|
|
1816
|
+
playerId,
|
|
1817
|
+
[...nextCards]
|
|
1818
|
+
);
|
|
1850
1819
|
}
|
|
1820
|
+
|
|
1821
|
+
// src/reducer/table/clone.ts
|
|
1851
1822
|
function cloneRuntimeBoardState(board) {
|
|
1852
1823
|
if (board.layout !== "generic") {
|
|
1853
1824
|
return {
|
|
@@ -1991,623 +1962,251 @@ function cloneRuntimeTable(table) {
|
|
|
1991
1962
|
)
|
|
1992
1963
|
};
|
|
1993
1964
|
}
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
];
|
|
1965
|
+
|
|
1966
|
+
// src/reducer/table/board-queries.ts
|
|
1967
|
+
function getBoard(table, boardId) {
|
|
1968
|
+
return table.boards.byId[boardId];
|
|
1999
1969
|
}
|
|
2000
|
-
function
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
1970
|
+
function getHexBoard(table, boardId) {
|
|
1971
|
+
return getBoard(table, boardId);
|
|
1972
|
+
}
|
|
1973
|
+
function getTiledBoard(table, boardId) {
|
|
1974
|
+
return getBoard(table, boardId);
|
|
1975
|
+
}
|
|
1976
|
+
function getSquareBoard(table, boardId) {
|
|
1977
|
+
return getBoard(table, boardId);
|
|
1978
|
+
}
|
|
1979
|
+
function getSpace(table, boardId, spaceId) {
|
|
1980
|
+
return getBoard(table, boardId).spaces[spaceId];
|
|
1981
|
+
}
|
|
1982
|
+
function getHexSpace(table, boardId, spaceId) {
|
|
1983
|
+
return getHexBoard(table, boardId).spaces[spaceId];
|
|
1984
|
+
}
|
|
1985
|
+
function getSquareSpace(table, boardId, spaceId) {
|
|
1986
|
+
return getSquareBoard(table, boardId).spaces[spaceId];
|
|
1987
|
+
}
|
|
1988
|
+
function getContainer(table, boardId, containerId) {
|
|
1989
|
+
return getBoard(table, boardId).containers[containerId];
|
|
1990
|
+
}
|
|
1991
|
+
function getEdge(table, boardId, edgeId) {
|
|
1992
|
+
const edge = getTiledBoard(table, boardId).edges.find(
|
|
1993
|
+
(candidate) => candidate.id === edgeId
|
|
1994
|
+
);
|
|
1995
|
+
if (!edge) {
|
|
1996
|
+
throw new Error(`Unknown edge '${edgeId}' on board '${boardId}'.`);
|
|
2007
1997
|
}
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
playerId,
|
|
2014
|
-
[...nextCards]
|
|
1998
|
+
return edge;
|
|
1999
|
+
}
|
|
2000
|
+
function getVertex(table, boardId, vertexId) {
|
|
2001
|
+
const vertex = getTiledBoard(table, boardId).vertices.find(
|
|
2002
|
+
(candidate) => candidate.id === vertexId
|
|
2015
2003
|
);
|
|
2016
|
-
|
|
2004
|
+
if (!vertex) {
|
|
2005
|
+
throw new Error(`Unknown vertex '${vertexId}' on board '${boardId}'.`);
|
|
2006
|
+
}
|
|
2007
|
+
return vertex;
|
|
2017
2008
|
}
|
|
2018
|
-
function
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
]);
|
|
2022
|
-
table.zones.perPlayer[zoneId] = ppWrite(
|
|
2023
|
-
table.zones.perPlayer[zoneId],
|
|
2024
|
-
playerId,
|
|
2025
|
-
[...nextCards]
|
|
2009
|
+
function getHexSpaceAt(table, boardId, q, r) {
|
|
2010
|
+
return Object.values(getHexBoard(table, boardId).spaces).find(
|
|
2011
|
+
(space) => space.q === q && space.r === r
|
|
2026
2012
|
);
|
|
2027
2013
|
}
|
|
2028
|
-
function
|
|
2029
|
-
|
|
2030
|
-
(
|
|
2031
|
-
const location = table.componentLocations[componentId];
|
|
2032
|
-
if (location?.type === "OnSpace") {
|
|
2033
|
-
table.componentLocations[componentId] = {
|
|
2034
|
-
...location,
|
|
2035
|
-
position: index
|
|
2036
|
-
};
|
|
2037
|
-
}
|
|
2038
|
-
}
|
|
2014
|
+
function getSquareSpaceAt(table, boardId, row, col) {
|
|
2015
|
+
return Object.values(getSquareBoard(table, boardId).spaces).find(
|
|
2016
|
+
(space) => space.row === row && space.col === col
|
|
2039
2017
|
);
|
|
2040
2018
|
}
|
|
2041
|
-
function
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
}
|
|
2019
|
+
function getSpaceEdges(table, boardId, spaceId) {
|
|
2020
|
+
return getTiledBoard(table, boardId).edges.filter((edge) => edge.spaceIds.includes(spaceId)).map((edge) => edge.id);
|
|
2021
|
+
}
|
|
2022
|
+
function getSpaceVertices(table, boardId, spaceId) {
|
|
2023
|
+
return getTiledBoard(table, boardId).vertices.filter((vertex) => vertex.spaceIds.includes(spaceId)).map((vertex) => vertex.id);
|
|
2024
|
+
}
|
|
2025
|
+
function getIncidentEdges(table, boardId, vertexId) {
|
|
2026
|
+
const tiledBoard = getTiledBoard(table, boardId);
|
|
2027
|
+
const vertex = tiledBoard.vertices.find(
|
|
2028
|
+
(candidate) => candidate.id === vertexId
|
|
2052
2029
|
);
|
|
2030
|
+
if (!vertex) {
|
|
2031
|
+
throw new Error(`Unknown vertex '${vertexId}' on board '${boardId}'.`);
|
|
2032
|
+
}
|
|
2033
|
+
const vertexSpaceIds = new Set(vertex.spaceIds);
|
|
2034
|
+
return tiledBoard.edges.filter(
|
|
2035
|
+
(edge) => edge.spaceIds.every((spaceId) => vertexSpaceIds.has(spaceId))
|
|
2036
|
+
).map((edge) => edge.id);
|
|
2053
2037
|
}
|
|
2054
|
-
function
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
});
|
|
2038
|
+
function getIncidentVertices(table, boardId, edgeId) {
|
|
2039
|
+
const tiledBoard = getTiledBoard(table, boardId);
|
|
2040
|
+
const edge = tiledBoard.edges.find((candidate) => candidate.id === edgeId);
|
|
2041
|
+
if (!edge) {
|
|
2042
|
+
throw new Error(`Unknown edge '${edgeId}' on board '${boardId}'.`);
|
|
2043
|
+
}
|
|
2044
|
+
const edgeSpaceIds = new Set(edge.spaceIds);
|
|
2045
|
+
return tiledBoard.vertices.filter(
|
|
2046
|
+
(vertex) => Array.from(edgeSpaceIds).every(
|
|
2047
|
+
(spaceId) => vertex.spaceIds.includes(spaceId)
|
|
2048
|
+
)
|
|
2049
|
+
).map((vertex) => vertex.id);
|
|
2067
2050
|
}
|
|
2068
|
-
function
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
if (location?.type === "OnVertex") {
|
|
2075
|
-
table.componentLocations[componentId] = {
|
|
2076
|
-
...location,
|
|
2077
|
-
position: index
|
|
2078
|
-
};
|
|
2051
|
+
function getRelatedSpaces(table, boardId, spaceId, relationTypeId) {
|
|
2052
|
+
const board = getBoard(table, boardId);
|
|
2053
|
+
const related = /* @__PURE__ */ new Set();
|
|
2054
|
+
for (const relation of board.relations) {
|
|
2055
|
+
if (relation.typeId !== relationTypeId) {
|
|
2056
|
+
continue;
|
|
2079
2057
|
}
|
|
2080
|
-
|
|
2058
|
+
if (relation.fromSpaceId === spaceId) {
|
|
2059
|
+
related.add(relation.toSpaceId);
|
|
2060
|
+
continue;
|
|
2061
|
+
}
|
|
2062
|
+
if (!relation.directed && relation.toSpaceId === spaceId) {
|
|
2063
|
+
related.add(relation.fromSpaceId);
|
|
2064
|
+
}
|
|
2065
|
+
}
|
|
2066
|
+
return [...related];
|
|
2081
2067
|
}
|
|
2082
|
-
function
|
|
2083
|
-
|
|
2068
|
+
function getAdjacentSpaces(table, boardId, spaceId) {
|
|
2069
|
+
return getRelatedSpaces(
|
|
2084
2070
|
table,
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
table.componentLocations[componentId] = {
|
|
2090
|
-
...location,
|
|
2091
|
-
position: index
|
|
2092
|
-
};
|
|
2093
|
-
}
|
|
2094
|
-
});
|
|
2071
|
+
boardId,
|
|
2072
|
+
spaceId,
|
|
2073
|
+
"adjacent"
|
|
2074
|
+
);
|
|
2095
2075
|
}
|
|
2096
|
-
function
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
return;
|
|
2076
|
+
function getSpaceDistance(table, boardId, fromSpaceId, toSpaceId) {
|
|
2077
|
+
if (fromSpaceId === toSpaceId) {
|
|
2078
|
+
return 0;
|
|
2100
2079
|
}
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
if (currentLocation.type === "InHand") {
|
|
2122
|
-
const nextCards = ensureArray(
|
|
2123
|
-
ppRead(table.hands[currentLocation.handId], currentLocation.playerId)
|
|
2124
|
-
).filter((candidate) => candidate !== componentId);
|
|
2125
|
-
syncPlayerZoneWithHand(
|
|
2126
|
-
table,
|
|
2127
|
-
currentLocation.handId,
|
|
2128
|
-
currentLocation.playerId,
|
|
2129
|
-
nextCards
|
|
2130
|
-
);
|
|
2131
|
-
nextCards.forEach((cardId, index) => {
|
|
2132
|
-
const location = table.componentLocations[cardId];
|
|
2133
|
-
if (location?.type === "InHand") {
|
|
2134
|
-
table.componentLocations[cardId] = {
|
|
2135
|
-
...location,
|
|
2136
|
-
position: index
|
|
2137
|
-
};
|
|
2138
|
-
}
|
|
2139
|
-
});
|
|
2140
|
-
return;
|
|
2141
|
-
}
|
|
2142
|
-
if (currentLocation.type === "OnSpace") {
|
|
2143
|
-
delete table.componentLocations[componentId];
|
|
2144
|
-
reindexSpaceOccupants(
|
|
2145
|
-
table,
|
|
2146
|
-
currentLocation.boardId,
|
|
2147
|
-
currentLocation.spaceId
|
|
2148
|
-
);
|
|
2149
|
-
return;
|
|
2150
|
-
}
|
|
2151
|
-
if (currentLocation.type === "InZone") {
|
|
2152
|
-
if (currentLocation.zoneId in table.zones.shared) {
|
|
2153
|
-
const nextComponents = ensureArray(
|
|
2154
|
-
table.zones.shared[currentLocation.zoneId]
|
|
2155
|
-
).filter((candidate) => candidate !== componentId);
|
|
2156
|
-
syncSharedZoneWithDeck(
|
|
2157
|
-
table,
|
|
2158
|
-
currentLocation.zoneId,
|
|
2159
|
-
nextComponents
|
|
2160
|
-
);
|
|
2161
|
-
nextComponents.forEach((currentComponentId, index) => {
|
|
2162
|
-
const location = table.componentLocations[currentComponentId];
|
|
2163
|
-
if (location?.type === "InZone") {
|
|
2164
|
-
table.componentLocations[currentComponentId] = {
|
|
2165
|
-
...location,
|
|
2166
|
-
position: index
|
|
2167
|
-
};
|
|
2168
|
-
}
|
|
2169
|
-
});
|
|
2170
|
-
}
|
|
2171
|
-
delete table.componentLocations[componentId];
|
|
2172
|
-
return;
|
|
2173
|
-
}
|
|
2174
|
-
if (currentLocation.type === "InContainer") {
|
|
2175
|
-
delete table.componentLocations[componentId];
|
|
2176
|
-
reindexContainerOccupants(
|
|
2177
|
-
table,
|
|
2178
|
-
currentLocation.boardId,
|
|
2179
|
-
currentLocation.containerId
|
|
2180
|
-
);
|
|
2181
|
-
return;
|
|
2182
|
-
}
|
|
2183
|
-
if (currentLocation.type === "OnEdge") {
|
|
2184
|
-
delete table.componentLocations[componentId];
|
|
2185
|
-
reindexEdgeOccupants(
|
|
2186
|
-
table,
|
|
2187
|
-
currentLocation.boardId,
|
|
2188
|
-
currentLocation.edgeId
|
|
2189
|
-
);
|
|
2190
|
-
return;
|
|
2191
|
-
}
|
|
2192
|
-
if (currentLocation.type === "OnVertex") {
|
|
2193
|
-
delete table.componentLocations[componentId];
|
|
2194
|
-
reindexVertexOccupants(
|
|
2195
|
-
table,
|
|
2196
|
-
currentLocation.boardId,
|
|
2197
|
-
currentLocation.vertexId
|
|
2198
|
-
);
|
|
2199
|
-
return;
|
|
2200
|
-
}
|
|
2201
|
-
if (currentLocation.type === "InSlot") {
|
|
2202
|
-
delete table.componentLocations[componentId];
|
|
2203
|
-
reindexSlotOccupants(table, currentLocation.host, currentLocation.slotId);
|
|
2204
|
-
return;
|
|
2205
|
-
}
|
|
2206
|
-
delete table.componentLocations[componentId];
|
|
2207
|
-
}
|
|
2208
|
-
function appendToDeck(table, deckId, cardId, playedBy = null, position = "bottom") {
|
|
2209
|
-
const nextTable = cloneRuntimeTable(table);
|
|
2210
|
-
assertZoneScope(
|
|
2211
|
-
nextTable,
|
|
2212
|
-
deckId,
|
|
2213
|
-
"shared",
|
|
2214
|
-
"addCardToSharedZone",
|
|
2215
|
-
"zoneId"
|
|
2216
|
-
);
|
|
2217
|
-
const deckCards = [
|
|
2218
|
-
...ensureArray(nextTable.decks[deckId])
|
|
2219
|
-
];
|
|
2220
|
-
assertCardAllowedInZone(nextTable, deckId, cardId);
|
|
2221
|
-
if (position === "top") {
|
|
2222
|
-
deckCards.unshift(cardId);
|
|
2223
|
-
} else {
|
|
2224
|
-
deckCards.push(cardId);
|
|
2225
|
-
}
|
|
2226
|
-
syncSharedZoneWithDeck(nextTable, deckId, deckCards);
|
|
2227
|
-
for (const [index, currentCardId] of deckCards.entries()) {
|
|
2228
|
-
if (currentCardId === cardId) {
|
|
2229
|
-
nextTable.componentLocations[currentCardId] = {
|
|
2230
|
-
type: "InDeck",
|
|
2231
|
-
deckId,
|
|
2232
|
-
playedBy,
|
|
2233
|
-
position: index
|
|
2234
|
-
};
|
|
2235
|
-
continue;
|
|
2236
|
-
}
|
|
2237
|
-
const existing = nextTable.componentLocations[currentCardId];
|
|
2238
|
-
nextTable.componentLocations[currentCardId] = {
|
|
2239
|
-
type: "InDeck",
|
|
2240
|
-
deckId,
|
|
2241
|
-
playedBy: existing?.type === "InDeck" ? existing.playedBy : null,
|
|
2242
|
-
position: index
|
|
2243
|
-
};
|
|
2244
|
-
}
|
|
2245
|
-
nextTable.ownerOfCard[cardId] = playedBy;
|
|
2246
|
-
nextTable.visibility[cardId] = {
|
|
2247
|
-
faceUp: true
|
|
2248
|
-
};
|
|
2249
|
-
return nextTable;
|
|
2250
|
-
}
|
|
2251
|
-
function removeFromDeck(table, deckId, cardId) {
|
|
2252
|
-
const nextTable = cloneRuntimeTable(table);
|
|
2253
|
-
assertZoneScope(
|
|
2254
|
-
nextTable,
|
|
2255
|
-
deckId,
|
|
2256
|
-
"shared",
|
|
2257
|
-
"removeCardFromSharedZone",
|
|
2258
|
-
"zoneId"
|
|
2259
|
-
);
|
|
2260
|
-
const remaining = ensureArray(nextTable.decks[deckId]).filter(
|
|
2261
|
-
(candidate) => candidate !== cardId
|
|
2262
|
-
);
|
|
2263
|
-
syncSharedZoneWithDeck(nextTable, deckId, remaining);
|
|
2264
|
-
for (const [index, currentCardId] of remaining.entries()) {
|
|
2265
|
-
const currentLocation = nextTable.componentLocations[currentCardId];
|
|
2266
|
-
if (currentLocation?.type === "InDeck") {
|
|
2267
|
-
nextTable.componentLocations[currentCardId] = {
|
|
2268
|
-
...currentLocation,
|
|
2269
|
-
position: index
|
|
2270
|
-
};
|
|
2271
|
-
}
|
|
2272
|
-
}
|
|
2273
|
-
return nextTable;
|
|
2274
|
-
}
|
|
2275
|
-
function computeVisibilityForPlayerZone(table, zoneId, playerId) {
|
|
2276
|
-
const mode = table.handVisibility[zoneId];
|
|
2277
|
-
if (mode === "all" || mode === "public") {
|
|
2278
|
-
return { faceUp: true };
|
|
2279
|
-
}
|
|
2280
|
-
return { faceUp: false, visibleTo: [playerId] };
|
|
2281
|
-
}
|
|
2282
|
-
function moveFromHandToDeck(options) {
|
|
2283
|
-
const nextTable = cloneRuntimeTable(options.table);
|
|
2284
|
-
assertZoneScope(
|
|
2285
|
-
nextTable,
|
|
2286
|
-
options.handId,
|
|
2287
|
-
"perPlayer",
|
|
2288
|
-
"moveCardFromPlayerZoneToSharedZone",
|
|
2289
|
-
"fromZoneId"
|
|
2290
|
-
);
|
|
2291
|
-
assertZoneScope(
|
|
2292
|
-
nextTable,
|
|
2293
|
-
options.deckId,
|
|
2294
|
-
"shared",
|
|
2295
|
-
"moveCardFromPlayerZoneToSharedZone",
|
|
2296
|
-
"toZoneId"
|
|
2297
|
-
);
|
|
2298
|
-
const currentHand = ensureArray(
|
|
2299
|
-
ppRead(nextTable.hands[options.handId], options.playerId)
|
|
2300
|
-
).filter((candidate) => candidate !== options.cardId);
|
|
2301
|
-
syncPlayerZoneWithHand(
|
|
2302
|
-
nextTable,
|
|
2303
|
-
options.handId,
|
|
2304
|
-
options.playerId,
|
|
2305
|
-
currentHand
|
|
2306
|
-
);
|
|
2307
|
-
for (const [index, currentCardId] of currentHand.entries()) {
|
|
2308
|
-
nextTable.componentLocations[currentCardId] = {
|
|
2309
|
-
type: "InHand",
|
|
2310
|
-
handId: options.handId,
|
|
2311
|
-
playerId: options.playerId,
|
|
2312
|
-
position: index
|
|
2313
|
-
};
|
|
2314
|
-
}
|
|
2315
|
-
nextTable.ownerOfCard[options.cardId] = options.playedBy ?? options.playerId;
|
|
2316
|
-
nextTable.visibility[options.cardId] = {
|
|
2317
|
-
faceUp: true
|
|
2318
|
-
};
|
|
2319
|
-
return appendToDeck(
|
|
2320
|
-
nextTable,
|
|
2321
|
-
options.deckId,
|
|
2322
|
-
options.cardId,
|
|
2323
|
-
options.playedBy ?? options.playerId,
|
|
2324
|
-
options.position ?? "bottom"
|
|
2325
|
-
);
|
|
2326
|
-
}
|
|
2327
|
-
function setActivePlayers(state, activePlayers) {
|
|
2328
|
-
return {
|
|
2329
|
-
...state,
|
|
2330
|
-
flow: {
|
|
2331
|
-
...state.flow,
|
|
2332
|
-
activePlayers
|
|
2333
|
-
}
|
|
2334
|
-
};
|
|
2335
|
-
}
|
|
2336
|
-
function setPhaseState(state, phaseState) {
|
|
2337
|
-
return {
|
|
2338
|
-
...state,
|
|
2339
|
-
phase: phaseState
|
|
2340
|
-
};
|
|
2341
|
-
}
|
|
2342
|
-
function getSharedZoneCards(table, zoneId) {
|
|
2343
|
-
assertZoneScope(
|
|
2344
|
-
table,
|
|
2345
|
-
zoneId,
|
|
2346
|
-
"shared",
|
|
2347
|
-
"getSharedZoneCards",
|
|
2348
|
-
"zoneId"
|
|
2349
|
-
);
|
|
2350
|
-
return [
|
|
2351
|
-
...ensureArray(table.zones.shared[zoneId] ?? table.decks[zoneId])
|
|
2352
|
-
];
|
|
2353
|
-
}
|
|
2354
|
-
function getPlayerZoneCards(table, playerId, zoneId) {
|
|
2355
|
-
assertZoneScope(
|
|
2356
|
-
table,
|
|
2357
|
-
zoneId,
|
|
2358
|
-
"perPlayer",
|
|
2359
|
-
"getPlayerZoneCards",
|
|
2360
|
-
"zoneId"
|
|
2361
|
-
);
|
|
2362
|
-
const cards = ppRead(table.zones.perPlayer[zoneId], playerId) ?? ppRead(table.hands[zoneId], playerId);
|
|
2363
|
-
return [
|
|
2364
|
-
...ensureArray(cards)
|
|
2365
|
-
];
|
|
2366
|
-
}
|
|
2367
|
-
function collectZoneIds(...sources) {
|
|
2368
|
-
const seen = /* @__PURE__ */ new Set();
|
|
2369
|
-
for (const source of sources) {
|
|
2370
|
-
if (!source) continue;
|
|
2371
|
-
for (const key of Object.keys(source)) {
|
|
2372
|
-
seen.add(key);
|
|
2080
|
+
const visited = /* @__PURE__ */ new Set([fromSpaceId]);
|
|
2081
|
+
let frontier = [fromSpaceId];
|
|
2082
|
+
let distance = 0;
|
|
2083
|
+
while (frontier.length > 0) {
|
|
2084
|
+
distance += 1;
|
|
2085
|
+
const nextFrontier = [];
|
|
2086
|
+
for (const currentSpaceId of frontier) {
|
|
2087
|
+
for (const neighborId of getAdjacentSpaces(
|
|
2088
|
+
table,
|
|
2089
|
+
boardId,
|
|
2090
|
+
currentSpaceId
|
|
2091
|
+
)) {
|
|
2092
|
+
if (neighborId === toSpaceId) {
|
|
2093
|
+
return distance;
|
|
2094
|
+
}
|
|
2095
|
+
if (!visited.has(neighborId)) {
|
|
2096
|
+
visited.add(neighborId);
|
|
2097
|
+
nextFrontier.push(neighborId);
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2373
2100
|
}
|
|
2101
|
+
frontier = nextFrontier;
|
|
2374
2102
|
}
|
|
2375
|
-
return
|
|
2103
|
+
return Number.POSITIVE_INFINITY;
|
|
2376
2104
|
}
|
|
2377
|
-
function
|
|
2378
|
-
const
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2105
|
+
function getSquareNeighbors(table, boardId, spaceId, options = {}) {
|
|
2106
|
+
const board = getSquareBoard(table, boardId);
|
|
2107
|
+
const space = getSquareSpace(table, boardId, spaceId);
|
|
2108
|
+
const offsets = options.mode === "diagonal" ? [
|
|
2109
|
+
[-1, -1],
|
|
2110
|
+
[-1, 1],
|
|
2111
|
+
[1, -1],
|
|
2112
|
+
[1, 1]
|
|
2113
|
+
] : options.mode === "all" ? [
|
|
2114
|
+
[-1, 0],
|
|
2115
|
+
[0, 1],
|
|
2116
|
+
[1, 0],
|
|
2117
|
+
[0, -1],
|
|
2118
|
+
[-1, -1],
|
|
2119
|
+
[-1, 1],
|
|
2120
|
+
[1, -1],
|
|
2121
|
+
[1, 1]
|
|
2122
|
+
] : [
|
|
2123
|
+
[-1, 0],
|
|
2124
|
+
[0, 1],
|
|
2125
|
+
[1, 0],
|
|
2126
|
+
[0, -1]
|
|
2127
|
+
];
|
|
2128
|
+
return offsets.map(
|
|
2129
|
+
([rowOffset, colOffset]) => Object.values(board.spaces).find(
|
|
2130
|
+
(candidate) => candidate.row === space.row + rowOffset && candidate.col === space.col + colOffset
|
|
2131
|
+
)
|
|
2132
|
+
).filter((candidate) => candidate !== void 0).map((candidate) => candidate.id);
|
|
2390
2133
|
}
|
|
2391
|
-
function
|
|
2392
|
-
const
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
zoneId
|
|
2398
|
-
);
|
|
2399
|
-
}
|
|
2400
|
-
return result;
|
|
2134
|
+
function getSquareDistance(table, boardId, fromSpaceId, toSpaceId, options = {}) {
|
|
2135
|
+
const from = getSquareSpace(table, boardId, fromSpaceId);
|
|
2136
|
+
const to = getSquareSpace(table, boardId, toSpaceId);
|
|
2137
|
+
const rowDistance = Math.abs(from.row - to.row);
|
|
2138
|
+
const colDistance = Math.abs(from.col - to.col);
|
|
2139
|
+
return options.metric === "chebyshev" ? Math.max(rowDistance, colDistance) : rowDistance + colDistance;
|
|
2401
2140
|
}
|
|
2402
|
-
function
|
|
2403
|
-
|
|
2404
|
-
return {
|
|
2405
|
-
id: card.id,
|
|
2406
|
-
cardType: card.cardType,
|
|
2407
|
-
name: card.name,
|
|
2408
|
-
text: card.text,
|
|
2409
|
-
properties: card.properties
|
|
2410
|
-
};
|
|
2141
|
+
function getBoardsByTypeId(table, typeId) {
|
|
2142
|
+
return Object.entries(table.boards.byId).filter(([, board]) => board.typeId === typeId).map(([boardId]) => boardId);
|
|
2411
2143
|
}
|
|
2412
|
-
function
|
|
2413
|
-
return Object.
|
|
2414
|
-
cardIds.map((cardId) => [
|
|
2415
|
-
cardId,
|
|
2416
|
-
table.cards[cardId] ? getCard(table, cardId) : void 0
|
|
2417
|
-
])
|
|
2418
|
-
);
|
|
2144
|
+
function getSpacesByTypeId(table, boardId, typeId) {
|
|
2145
|
+
return Object.entries(getBoard(table, boardId).spaces).filter(([, space]) => space.typeId === typeId).map(([spaceId]) => spaceId);
|
|
2419
2146
|
}
|
|
2420
|
-
function
|
|
2421
|
-
|
|
2422
|
-
return {
|
|
2423
|
-
cardIds,
|
|
2424
|
-
cardsById: getCardsById(table, cardIds)
|
|
2425
|
-
};
|
|
2147
|
+
function getEdgesByTypeId(table, boardId, typeId) {
|
|
2148
|
+
return getTiledBoard(table, boardId).edges.filter((edge) => edge.typeId === typeId).map((edge) => edge.id);
|
|
2426
2149
|
}
|
|
2427
|
-
function
|
|
2428
|
-
|
|
2429
|
-
return {
|
|
2430
|
-
cardIds,
|
|
2431
|
-
cardsById: getCardsById(table, cardIds)
|
|
2432
|
-
};
|
|
2150
|
+
function getVerticesByTypeId(table, boardId, typeId) {
|
|
2151
|
+
return getTiledBoard(table, boardId).vertices.filter((vertex) => vertex.typeId === typeId).map((vertex) => vertex.id);
|
|
2433
2152
|
}
|
|
2434
|
-
function
|
|
2153
|
+
function getComponentsOnSpace(table, boardId, spaceId) {
|
|
2154
|
+
const zoneId = getSpace(table, boardId, spaceId).zoneId;
|
|
2435
2155
|
return orderedComponentIdsForLocation(
|
|
2436
2156
|
table,
|
|
2437
|
-
(location) =>
|
|
2438
|
-
)
|
|
2439
|
-
pieceId: componentId,
|
|
2440
|
-
playerId: componentPlayerId(
|
|
2441
|
-
table,
|
|
2442
|
-
componentId
|
|
2443
|
-
),
|
|
2444
|
-
slotId,
|
|
2445
|
-
data: componentData(table, componentId)
|
|
2446
|
-
}));
|
|
2157
|
+
(location) => location.type === "OnSpace" && location.boardId === boardId && location.spaceId === spaceId || location.type === "InZone" && typeof zoneId === "string" && zoneId.length > 0 && location.zoneId === zoneId
|
|
2158
|
+
);
|
|
2447
2159
|
}
|
|
2448
|
-
function
|
|
2449
|
-
const
|
|
2450
|
-
orderedComponentIdsForLocation(
|
|
2160
|
+
function getComponentsInContainer(table, boardId, containerId) {
|
|
2161
|
+
const zoneId = getContainer(table, boardId, containerId).zoneId;
|
|
2162
|
+
return orderedComponentIdsForLocation(
|
|
2451
2163
|
table,
|
|
2452
|
-
(location) =>
|
|
2453
|
-
).forEach((componentId) => {
|
|
2454
|
-
const location = table.componentLocations[componentId];
|
|
2455
|
-
if (!location || !matchesSlotHost(location, host)) {
|
|
2456
|
-
return;
|
|
2457
|
-
}
|
|
2458
|
-
const slotOccupant = {
|
|
2459
|
-
pieceId: componentId,
|
|
2460
|
-
playerId: componentPlayerId(
|
|
2461
|
-
table,
|
|
2462
|
-
componentId
|
|
2463
|
-
),
|
|
2464
|
-
slotId: location.slotId,
|
|
2465
|
-
data: componentData(table, componentId)
|
|
2466
|
-
};
|
|
2467
|
-
(occupantsBySlot[location.slotId] ??= []).push(slotOccupant);
|
|
2468
|
-
});
|
|
2469
|
-
return occupantsBySlot;
|
|
2470
|
-
}
|
|
2471
|
-
function getCardOwner(table, cardId) {
|
|
2472
|
-
return table.ownerOfCard[cardId];
|
|
2473
|
-
}
|
|
2474
|
-
function getCardVisibility(table, cardId) {
|
|
2475
|
-
return table.visibility[cardId];
|
|
2476
|
-
}
|
|
2477
|
-
function getPlayerOrder(table) {
|
|
2478
|
-
return table.playerOrder;
|
|
2479
|
-
}
|
|
2480
|
-
function getPlayerResources(table, playerId) {
|
|
2481
|
-
return perPlayerGet(
|
|
2482
|
-
table.resources,
|
|
2483
|
-
playerId
|
|
2164
|
+
(location) => location.type === "InContainer" && location.boardId === boardId && location.containerId === containerId || location.type === "InZone" && typeof zoneId === "string" && zoneId.length > 0 && location.zoneId === zoneId
|
|
2484
2165
|
);
|
|
2485
2166
|
}
|
|
2486
|
-
function
|
|
2487
|
-
|
|
2488
|
-
table
|
|
2489
|
-
|
|
2167
|
+
function getComponentsOnEdge(table, boardId, edgeId) {
|
|
2168
|
+
return orderedComponentIdsForLocation(
|
|
2169
|
+
table,
|
|
2170
|
+
(location) => location.type === "OnEdge" && location.boardId === boardId && location.edgeId === edgeId
|
|
2490
2171
|
);
|
|
2491
|
-
if (!playerResources) return 0;
|
|
2492
|
-
const value = playerResources[resourceId];
|
|
2493
|
-
return typeof value === "number" ? value : 0;
|
|
2494
2172
|
}
|
|
2495
|
-
function
|
|
2496
|
-
|
|
2497
|
-
table
|
|
2498
|
-
|
|
2173
|
+
function getComponentsOnVertex(table, boardId, vertexId) {
|
|
2174
|
+
return orderedComponentIdsForLocation(
|
|
2175
|
+
table,
|
|
2176
|
+
(location) => location.type === "OnVertex" && location.boardId === boardId && location.vertexId === vertexId
|
|
2499
2177
|
);
|
|
2500
|
-
if (!playerResources) return 0;
|
|
2501
|
-
let total = 0;
|
|
2502
|
-
for (const key of Object.keys(playerResources)) {
|
|
2503
|
-
const value = playerResources[key];
|
|
2504
|
-
if (typeof value === "number") total += value;
|
|
2505
|
-
}
|
|
2506
|
-
return total;
|
|
2507
|
-
}
|
|
2508
|
-
function getNextPlayerInOrder(table, playerId) {
|
|
2509
|
-
const order = table.playerOrder;
|
|
2510
|
-
if (order.length === 0) return null;
|
|
2511
|
-
const idx = order.indexOf(playerId);
|
|
2512
|
-
if (idx < 0) return null;
|
|
2513
|
-
return order[(idx + 1) % order.length] ?? null;
|
|
2514
|
-
}
|
|
2515
|
-
function forEachResourceEntry(amounts, visit) {
|
|
2516
|
-
for (const resourceId of Object.keys(amounts)) {
|
|
2517
|
-
const amount = amounts[resourceId];
|
|
2518
|
-
if (typeof amount !== "number" || amount === 0) continue;
|
|
2519
|
-
visit(resourceId, amount);
|
|
2520
|
-
}
|
|
2521
|
-
}
|
|
2522
|
-
function canAffordResources(table, playerId, amounts) {
|
|
2523
|
-
for (const resourceId of Object.keys(amounts)) {
|
|
2524
|
-
const required = amounts[resourceId];
|
|
2525
|
-
if (typeof required !== "number" || required <= 0) continue;
|
|
2526
|
-
if (getPlayerResourceAmount(table, playerId, resourceId) < required) {
|
|
2527
|
-
return false;
|
|
2528
|
-
}
|
|
2529
|
-
}
|
|
2530
|
-
return true;
|
|
2531
|
-
}
|
|
2532
|
-
function getMissingResources(table, playerId, amounts) {
|
|
2533
|
-
const missing = {};
|
|
2534
|
-
for (const resourceId of Object.keys(amounts)) {
|
|
2535
|
-
const required = amounts[resourceId];
|
|
2536
|
-
if (typeof required !== "number" || required <= 0) continue;
|
|
2537
|
-
const have = getPlayerResourceAmount(table, playerId, resourceId);
|
|
2538
|
-
if (have < required) missing[resourceId] = required - have;
|
|
2539
|
-
}
|
|
2540
|
-
return missing;
|
|
2541
|
-
}
|
|
2542
|
-
function withPlayerResources(table, playerId, nextForPlayer) {
|
|
2543
|
-
return {
|
|
2544
|
-
...table,
|
|
2545
|
-
resources: perPlayerSet(
|
|
2546
|
-
table.resources,
|
|
2547
|
-
playerId,
|
|
2548
|
-
nextForPlayer
|
|
2549
|
-
)
|
|
2550
|
-
};
|
|
2551
2178
|
}
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
) ?? {};
|
|
2557
|
-
const next = { ...prev };
|
|
2558
|
-
forEachResourceEntry(amounts, (resourceId, amount) => {
|
|
2559
|
-
if (amount < 0) {
|
|
2560
|
-
throw new Error(
|
|
2561
|
-
`addPlayerResources: negative amount for resource '${resourceId}'. Use spendPlayerResources or transferPlayerResources instead.`
|
|
2562
|
-
);
|
|
2563
|
-
}
|
|
2564
|
-
next[resourceId] = (next[resourceId] ?? 0) + amount;
|
|
2565
|
-
});
|
|
2566
|
-
return withPlayerResources(table, playerId, next);
|
|
2179
|
+
|
|
2180
|
+
// src/reducer/table/card-validation.ts
|
|
2181
|
+
function allowedCardSetIdsForZone(table, zoneId) {
|
|
2182
|
+
return table.zones.cardSetIdsByZoneId?.[zoneId] ?? [];
|
|
2567
2183
|
}
|
|
2568
|
-
function
|
|
2569
|
-
|
|
2570
|
-
|
|
2184
|
+
function assertCardAllowedInZone(table, zoneId, componentId) {
|
|
2185
|
+
const card = table.cards[componentId];
|
|
2186
|
+
if (!card) {
|
|
2187
|
+
return;
|
|
2188
|
+
}
|
|
2189
|
+
const allowedCardSetIds = allowedCardSetIdsForZone(table, zoneId);
|
|
2190
|
+
if (allowedCardSetIds.length > 0 && !allowedCardSetIds.includes(card.cardSetId)) {
|
|
2571
2191
|
throw new Error(
|
|
2572
|
-
`
|
|
2573
|
-
missing
|
|
2574
|
-
)}. Check canAfford in your validate step first.`
|
|
2192
|
+
`Card '${componentId}' from card set '${card.cardSetId}' cannot enter zone '${zoneId}'.`
|
|
2575
2193
|
);
|
|
2576
2194
|
}
|
|
2577
|
-
const prev = perPlayerGet(
|
|
2578
|
-
table.resources,
|
|
2579
|
-
playerId
|
|
2580
|
-
) ?? {};
|
|
2581
|
-
const next = { ...prev };
|
|
2582
|
-
forEachResourceEntry(amounts, (resourceId, amount) => {
|
|
2583
|
-
if (amount < 0) {
|
|
2584
|
-
throw new Error(
|
|
2585
|
-
`spendPlayerResources: negative amount for resource '${resourceId}'. Pass positive amounts \u2014 the op deducts them from the player.`
|
|
2586
|
-
);
|
|
2587
|
-
}
|
|
2588
|
-
next[resourceId] = Math.max(0, (next[resourceId] ?? 0) - amount);
|
|
2589
|
-
});
|
|
2590
|
-
return withPlayerResources(table, playerId, next);
|
|
2591
|
-
}
|
|
2592
|
-
function transferPlayerResources(table, fromPlayerId, toPlayerId, amounts) {
|
|
2593
|
-
const afterSpend = spendPlayerResources(table, fromPlayerId, amounts);
|
|
2594
|
-
return addPlayerResources(afterSpend, toPlayerId, amounts);
|
|
2595
2195
|
}
|
|
2596
|
-
function
|
|
2597
|
-
|
|
2196
|
+
function assertCardAllowedInContainer(table, boardId, containerId, componentId) {
|
|
2197
|
+
const card = table.cards[componentId];
|
|
2198
|
+
if (!card) {
|
|
2199
|
+
return;
|
|
2200
|
+
}
|
|
2201
|
+
const allowedCardSetIds = getContainer(table, boardId, containerId).allowedCardSetIds ?? [];
|
|
2202
|
+
if (allowedCardSetIds.length > 0 && !allowedCardSetIds.includes(card.cardSetId)) {
|
|
2598
2203
|
throw new Error(
|
|
2599
|
-
`
|
|
2204
|
+
`Card '${componentId}' from card set '${card.cardSetId}' cannot enter container '${containerId}' on board '${boardId}'.`
|
|
2600
2205
|
);
|
|
2601
2206
|
}
|
|
2602
|
-
const prev = perPlayerGet(
|
|
2603
|
-
table.resources,
|
|
2604
|
-
playerId
|
|
2605
|
-
) ?? {};
|
|
2606
|
-
return withPlayerResources(table, playerId, {
|
|
2607
|
-
...prev,
|
|
2608
|
-
[resourceId]: amount
|
|
2609
|
-
});
|
|
2610
2207
|
}
|
|
2208
|
+
|
|
2209
|
+
// src/reducer/table/component-locations.ts
|
|
2611
2210
|
function getComponentLocation(table, componentId) {
|
|
2612
2211
|
return table.componentLocations[componentId];
|
|
2613
2212
|
}
|
|
@@ -2726,229 +2325,493 @@ function getComponentSlotLocation(table, componentId) {
|
|
|
2726
2325
|
location
|
|
2727
2326
|
};
|
|
2728
2327
|
}
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
return getBoard(table, boardId);
|
|
2734
|
-
}
|
|
2735
|
-
function getTiledBoard(table, boardId) {
|
|
2736
|
-
return getBoard(table, boardId);
|
|
2737
|
-
}
|
|
2738
|
-
function getSquareBoard(table, boardId) {
|
|
2739
|
-
return getBoard(table, boardId);
|
|
2328
|
+
|
|
2329
|
+
// src/reducer/table/zone-queries.ts
|
|
2330
|
+
function matchesSlotHost(location, host, slotId) {
|
|
2331
|
+
return location.type === "InSlot" && location.host.kind === host.kind && location.host.id === host.id && (slotId === void 0 || location.slotId === slotId);
|
|
2740
2332
|
}
|
|
2741
|
-
function
|
|
2742
|
-
|
|
2333
|
+
function componentPlayerId(table, componentId) {
|
|
2334
|
+
const piece = table.pieces[componentId];
|
|
2335
|
+
if (piece) {
|
|
2336
|
+
return piece.ownerId ?? null;
|
|
2337
|
+
}
|
|
2338
|
+
const die = table.dice[componentId];
|
|
2339
|
+
if (die) {
|
|
2340
|
+
return die.ownerId ?? null;
|
|
2341
|
+
}
|
|
2342
|
+
const owner = table.ownerOfCard[componentId];
|
|
2343
|
+
if (owner !== void 0) {
|
|
2344
|
+
return owner ?? null;
|
|
2345
|
+
}
|
|
2346
|
+
return null;
|
|
2743
2347
|
}
|
|
2744
|
-
function
|
|
2745
|
-
|
|
2348
|
+
function componentData(table, componentId) {
|
|
2349
|
+
const piece = table.pieces[componentId];
|
|
2350
|
+
if (piece) {
|
|
2351
|
+
return piece.properties;
|
|
2352
|
+
}
|
|
2353
|
+
const die = table.dice[componentId];
|
|
2354
|
+
if (die) {
|
|
2355
|
+
return die.properties;
|
|
2356
|
+
}
|
|
2357
|
+
const card = table.cards[componentId];
|
|
2358
|
+
if (card) {
|
|
2359
|
+
return card.properties;
|
|
2360
|
+
}
|
|
2361
|
+
return void 0;
|
|
2746
2362
|
}
|
|
2747
|
-
function
|
|
2748
|
-
|
|
2363
|
+
function getSharedZoneCards(table, zoneId) {
|
|
2364
|
+
assertZoneScope(
|
|
2365
|
+
table,
|
|
2366
|
+
zoneId,
|
|
2367
|
+
"shared",
|
|
2368
|
+
"getSharedZoneCards",
|
|
2369
|
+
"zoneId"
|
|
2370
|
+
);
|
|
2371
|
+
return [
|
|
2372
|
+
...ensureArray(table.zones.shared[zoneId] ?? table.decks[zoneId])
|
|
2373
|
+
];
|
|
2749
2374
|
}
|
|
2750
|
-
function
|
|
2751
|
-
|
|
2375
|
+
function getPlayerZoneCards(table, playerId, zoneId) {
|
|
2376
|
+
assertZoneScope(
|
|
2377
|
+
table,
|
|
2378
|
+
zoneId,
|
|
2379
|
+
"perPlayer",
|
|
2380
|
+
"getPlayerZoneCards",
|
|
2381
|
+
"zoneId"
|
|
2382
|
+
);
|
|
2383
|
+
const cards = ppRead(table.zones.perPlayer[zoneId], playerId) ?? ppRead(table.hands[zoneId], playerId);
|
|
2384
|
+
return [
|
|
2385
|
+
...ensureArray(cards)
|
|
2386
|
+
];
|
|
2752
2387
|
}
|
|
2753
|
-
function
|
|
2754
|
-
const
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
throw new Error(
|
|
2761
|
-
`Card '${componentId}' from card set '${card.cardSetId}' cannot enter container '${containerId}' on board '${boardId}'.`
|
|
2762
|
-
);
|
|
2388
|
+
function collectZoneIds(...sources) {
|
|
2389
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2390
|
+
for (const source of sources) {
|
|
2391
|
+
if (!source) continue;
|
|
2392
|
+
for (const key of Object.keys(source)) {
|
|
2393
|
+
seen.add(key);
|
|
2394
|
+
}
|
|
2763
2395
|
}
|
|
2396
|
+
return [...seen];
|
|
2764
2397
|
}
|
|
2765
|
-
function
|
|
2766
|
-
const
|
|
2767
|
-
|
|
2398
|
+
function getAllSharedZoneCards(table) {
|
|
2399
|
+
const zoneIds = collectZoneIds(
|
|
2400
|
+
table.zones.shared,
|
|
2401
|
+
table.decks
|
|
2768
2402
|
);
|
|
2769
|
-
|
|
2770
|
-
|
|
2403
|
+
const result = {};
|
|
2404
|
+
for (const zoneId of zoneIds) {
|
|
2405
|
+
result[zoneId] = getSharedZoneCards(
|
|
2406
|
+
table,
|
|
2407
|
+
zoneId
|
|
2408
|
+
);
|
|
2771
2409
|
}
|
|
2772
|
-
return
|
|
2410
|
+
return result;
|
|
2773
2411
|
}
|
|
2774
|
-
function
|
|
2775
|
-
const
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2412
|
+
function getAllPlayerZoneCards(table, zoneId) {
|
|
2413
|
+
const result = {};
|
|
2414
|
+
for (const playerId of table.playerOrder) {
|
|
2415
|
+
result[playerId] = getPlayerZoneCards(
|
|
2416
|
+
table,
|
|
2417
|
+
playerId,
|
|
2418
|
+
zoneId
|
|
2419
|
+
);
|
|
2780
2420
|
}
|
|
2781
|
-
return
|
|
2421
|
+
return result;
|
|
2782
2422
|
}
|
|
2783
|
-
function
|
|
2784
|
-
|
|
2785
|
-
|
|
2423
|
+
function getCard(table, cardId) {
|
|
2424
|
+
const card = table.cards[cardId];
|
|
2425
|
+
return {
|
|
2426
|
+
id: card.id,
|
|
2427
|
+
cardType: card.cardType,
|
|
2428
|
+
name: card.name,
|
|
2429
|
+
text: card.text,
|
|
2430
|
+
properties: card.properties
|
|
2431
|
+
};
|
|
2432
|
+
}
|
|
2433
|
+
function getCardsById(table, cardIds) {
|
|
2434
|
+
return Object.fromEntries(
|
|
2435
|
+
cardIds.map((cardId) => [
|
|
2436
|
+
cardId,
|
|
2437
|
+
table.cards[cardId] ? getCard(table, cardId) : void 0
|
|
2438
|
+
])
|
|
2786
2439
|
);
|
|
2787
2440
|
}
|
|
2788
|
-
function
|
|
2789
|
-
|
|
2790
|
-
|
|
2441
|
+
function getSharedZoneCardCollection(table, zoneId) {
|
|
2442
|
+
const cardIds = getSharedZoneCards(table, zoneId);
|
|
2443
|
+
return {
|
|
2444
|
+
cardIds,
|
|
2445
|
+
cardsById: getCardsById(table, cardIds)
|
|
2446
|
+
};
|
|
2447
|
+
}
|
|
2448
|
+
function getPlayerZoneCardCollection(table, playerId, zoneId) {
|
|
2449
|
+
const cardIds = getPlayerZoneCards(table, playerId, zoneId);
|
|
2450
|
+
return {
|
|
2451
|
+
cardIds,
|
|
2452
|
+
cardsById: getCardsById(table, cardIds)
|
|
2453
|
+
};
|
|
2454
|
+
}
|
|
2455
|
+
function getSlotOccupants(table, host, slotId) {
|
|
2456
|
+
return orderedComponentIdsForLocation(
|
|
2457
|
+
table,
|
|
2458
|
+
(location) => matchesSlotHost(location, host, slotId)
|
|
2459
|
+
).map((componentId) => ({
|
|
2460
|
+
pieceId: componentId,
|
|
2461
|
+
playerId: componentPlayerId(
|
|
2462
|
+
table,
|
|
2463
|
+
componentId
|
|
2464
|
+
),
|
|
2465
|
+
slotId,
|
|
2466
|
+
data: componentData(table, componentId)
|
|
2467
|
+
}));
|
|
2468
|
+
}
|
|
2469
|
+
function getSlotOccupantsByHost(table, host) {
|
|
2470
|
+
const occupantsBySlot = {};
|
|
2471
|
+
orderedComponentIdsForLocation(
|
|
2472
|
+
table,
|
|
2473
|
+
(location) => matchesSlotHost(location, host)
|
|
2474
|
+
).forEach((componentId) => {
|
|
2475
|
+
const location = table.componentLocations[componentId];
|
|
2476
|
+
if (!location || !matchesSlotHost(location, host)) {
|
|
2477
|
+
return;
|
|
2478
|
+
}
|
|
2479
|
+
const slotOccupant = {
|
|
2480
|
+
pieceId: componentId,
|
|
2481
|
+
playerId: componentPlayerId(
|
|
2482
|
+
table,
|
|
2483
|
+
componentId
|
|
2484
|
+
),
|
|
2485
|
+
slotId: location.slotId,
|
|
2486
|
+
data: componentData(table, componentId)
|
|
2487
|
+
};
|
|
2488
|
+
(occupantsBySlot[location.slotId] ??= []).push(slotOccupant);
|
|
2489
|
+
});
|
|
2490
|
+
return occupantsBySlot;
|
|
2491
|
+
}
|
|
2492
|
+
function getCardOwner(table, cardId) {
|
|
2493
|
+
return table.ownerOfCard[cardId];
|
|
2494
|
+
}
|
|
2495
|
+
function getCardVisibility(table, cardId) {
|
|
2496
|
+
return table.visibility[cardId];
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2499
|
+
// src/reducer/table/resource-ops.ts
|
|
2500
|
+
function getPlayerOrder(table) {
|
|
2501
|
+
return table.playerOrder;
|
|
2502
|
+
}
|
|
2503
|
+
function getPlayerResources(table, playerId) {
|
|
2504
|
+
return perPlayerGet(
|
|
2505
|
+
table.resources,
|
|
2506
|
+
playerId
|
|
2791
2507
|
);
|
|
2792
2508
|
}
|
|
2793
|
-
function
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2509
|
+
function getPlayerResourceAmount(table, playerId, resourceId) {
|
|
2510
|
+
const playerResources = perPlayerGet(
|
|
2511
|
+
table.resources,
|
|
2512
|
+
playerId
|
|
2513
|
+
);
|
|
2514
|
+
if (!playerResources) return 0;
|
|
2515
|
+
const value = playerResources[resourceId];
|
|
2516
|
+
return typeof value === "number" ? value : 0;
|
|
2798
2517
|
}
|
|
2799
|
-
function
|
|
2800
|
-
const
|
|
2801
|
-
|
|
2802
|
-
|
|
2518
|
+
function getPlayerResourceTotal(table, playerId) {
|
|
2519
|
+
const playerResources = perPlayerGet(
|
|
2520
|
+
table.resources,
|
|
2521
|
+
playerId
|
|
2803
2522
|
);
|
|
2804
|
-
if (!
|
|
2805
|
-
|
|
2523
|
+
if (!playerResources) return 0;
|
|
2524
|
+
let total = 0;
|
|
2525
|
+
for (const key of Object.keys(playerResources)) {
|
|
2526
|
+
const value = playerResources[key];
|
|
2527
|
+
if (typeof value === "number") total += value;
|
|
2806
2528
|
}
|
|
2807
|
-
|
|
2808
|
-
return tiledBoard.edges.filter(
|
|
2809
|
-
(edge) => edge.spaceIds.every((spaceId) => vertexSpaceIds.has(spaceId))
|
|
2810
|
-
).map((edge) => edge.id);
|
|
2529
|
+
return total;
|
|
2811
2530
|
}
|
|
2812
|
-
function
|
|
2813
|
-
const
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2531
|
+
function getNextPlayerInOrder(table, playerId) {
|
|
2532
|
+
const order = table.playerOrder;
|
|
2533
|
+
if (order.length === 0) return null;
|
|
2534
|
+
const idx = order.indexOf(playerId);
|
|
2535
|
+
if (idx < 0) return null;
|
|
2536
|
+
return order[(idx + 1) % order.length] ?? null;
|
|
2537
|
+
}
|
|
2538
|
+
function forEachResourceEntry(amounts, visit) {
|
|
2539
|
+
for (const resourceId of Object.keys(amounts)) {
|
|
2540
|
+
const amount = amounts[resourceId];
|
|
2541
|
+
if (typeof amount !== "number" || amount === 0) continue;
|
|
2542
|
+
visit(resourceId, amount);
|
|
2817
2543
|
}
|
|
2818
|
-
const edgeSpaceIds = new Set(edge.spaceIds);
|
|
2819
|
-
return tiledBoard.vertices.filter(
|
|
2820
|
-
(vertex) => Array.from(edgeSpaceIds).every(
|
|
2821
|
-
(spaceId) => vertex.spaceIds.includes(spaceId)
|
|
2822
|
-
)
|
|
2823
|
-
).map((vertex) => vertex.id);
|
|
2824
2544
|
}
|
|
2825
|
-
function
|
|
2826
|
-
const
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
if (
|
|
2830
|
-
|
|
2831
|
-
}
|
|
2832
|
-
if (relation.fromSpaceId === spaceId) {
|
|
2833
|
-
related.add(relation.toSpaceId);
|
|
2834
|
-
continue;
|
|
2835
|
-
}
|
|
2836
|
-
if (!relation.directed && relation.toSpaceId === spaceId) {
|
|
2837
|
-
related.add(relation.fromSpaceId);
|
|
2545
|
+
function canAffordResources(table, playerId, amounts) {
|
|
2546
|
+
for (const resourceId of Object.keys(amounts)) {
|
|
2547
|
+
const required = amounts[resourceId];
|
|
2548
|
+
if (typeof required !== "number" || required <= 0) continue;
|
|
2549
|
+
if (getPlayerResourceAmount(table, playerId, resourceId) < required) {
|
|
2550
|
+
return false;
|
|
2838
2551
|
}
|
|
2839
2552
|
}
|
|
2840
|
-
return
|
|
2841
|
-
}
|
|
2842
|
-
function getAdjacentSpaces(table, boardId, spaceId) {
|
|
2843
|
-
return getRelatedSpaces(
|
|
2844
|
-
table,
|
|
2845
|
-
boardId,
|
|
2846
|
-
spaceId,
|
|
2847
|
-
"adjacent"
|
|
2848
|
-
);
|
|
2553
|
+
return true;
|
|
2849
2554
|
}
|
|
2850
|
-
function
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
while (frontier.length > 0) {
|
|
2858
|
-
distance += 1;
|
|
2859
|
-
const nextFrontier = [];
|
|
2860
|
-
for (const currentSpaceId of frontier) {
|
|
2861
|
-
for (const neighborId of getAdjacentSpaces(
|
|
2862
|
-
table,
|
|
2863
|
-
boardId,
|
|
2864
|
-
currentSpaceId
|
|
2865
|
-
)) {
|
|
2866
|
-
if (neighborId === toSpaceId) {
|
|
2867
|
-
return distance;
|
|
2868
|
-
}
|
|
2869
|
-
if (!visited.has(neighborId)) {
|
|
2870
|
-
visited.add(neighborId);
|
|
2871
|
-
nextFrontier.push(neighborId);
|
|
2872
|
-
}
|
|
2873
|
-
}
|
|
2874
|
-
}
|
|
2875
|
-
frontier = nextFrontier;
|
|
2555
|
+
function getMissingResources(table, playerId, amounts) {
|
|
2556
|
+
const missing = {};
|
|
2557
|
+
for (const resourceId of Object.keys(amounts)) {
|
|
2558
|
+
const required = amounts[resourceId];
|
|
2559
|
+
if (typeof required !== "number" || required <= 0) continue;
|
|
2560
|
+
const have = getPlayerResourceAmount(table, playerId, resourceId);
|
|
2561
|
+
if (have < required) missing[resourceId] = required - have;
|
|
2876
2562
|
}
|
|
2877
|
-
return
|
|
2563
|
+
return missing;
|
|
2878
2564
|
}
|
|
2879
|
-
function
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
[1, 1]
|
|
2887
|
-
] : options.mode === "all" ? [
|
|
2888
|
-
[-1, 0],
|
|
2889
|
-
[0, 1],
|
|
2890
|
-
[1, 0],
|
|
2891
|
-
[0, -1],
|
|
2892
|
-
[-1, -1],
|
|
2893
|
-
[-1, 1],
|
|
2894
|
-
[1, -1],
|
|
2895
|
-
[1, 1]
|
|
2896
|
-
] : [
|
|
2897
|
-
[-1, 0],
|
|
2898
|
-
[0, 1],
|
|
2899
|
-
[1, 0],
|
|
2900
|
-
[0, -1]
|
|
2901
|
-
];
|
|
2902
|
-
return offsets.map(
|
|
2903
|
-
([rowOffset, colOffset]) => Object.values(board.spaces).find(
|
|
2904
|
-
(candidate) => candidate.row === space.row + rowOffset && candidate.col === space.col + colOffset
|
|
2565
|
+
function withPlayerResources(table, playerId, nextForPlayer) {
|
|
2566
|
+
return {
|
|
2567
|
+
...table,
|
|
2568
|
+
resources: perPlayerSet(
|
|
2569
|
+
table.resources,
|
|
2570
|
+
playerId,
|
|
2571
|
+
nextForPlayer
|
|
2905
2572
|
)
|
|
2906
|
-
|
|
2907
|
-
}
|
|
2908
|
-
function getSquareDistance(table, boardId, fromSpaceId, toSpaceId, options = {}) {
|
|
2909
|
-
const from = getSquareSpace(table, boardId, fromSpaceId);
|
|
2910
|
-
const to = getSquareSpace(table, boardId, toSpaceId);
|
|
2911
|
-
const rowDistance = Math.abs(from.row - to.row);
|
|
2912
|
-
const colDistance = Math.abs(from.col - to.col);
|
|
2913
|
-
return options.metric === "chebyshev" ? Math.max(rowDistance, colDistance) : rowDistance + colDistance;
|
|
2914
|
-
}
|
|
2915
|
-
function getBoardsByTypeId(table, typeId) {
|
|
2916
|
-
return Object.entries(table.boards.byId).filter(([, board]) => board.typeId === typeId).map(([boardId]) => boardId);
|
|
2573
|
+
};
|
|
2917
2574
|
}
|
|
2918
|
-
function
|
|
2919
|
-
|
|
2575
|
+
function addPlayerResources(table, playerId, amounts) {
|
|
2576
|
+
const prev = perPlayerGet(
|
|
2577
|
+
table.resources,
|
|
2578
|
+
playerId
|
|
2579
|
+
) ?? {};
|
|
2580
|
+
const next = { ...prev };
|
|
2581
|
+
forEachResourceEntry(amounts, (resourceId, amount) => {
|
|
2582
|
+
if (amount < 0) {
|
|
2583
|
+
throw new Error(
|
|
2584
|
+
`addPlayerResources: negative amount for resource '${resourceId}'. Use spendPlayerResources or transferPlayerResources instead.`
|
|
2585
|
+
);
|
|
2586
|
+
}
|
|
2587
|
+
next[resourceId] = (next[resourceId] ?? 0) + amount;
|
|
2588
|
+
});
|
|
2589
|
+
return withPlayerResources(table, playerId, next);
|
|
2920
2590
|
}
|
|
2921
|
-
function
|
|
2922
|
-
|
|
2591
|
+
function spendPlayerResources(table, playerId, amounts) {
|
|
2592
|
+
if (!canAffordResources(table, playerId, amounts)) {
|
|
2593
|
+
const missing = getMissingResources(table, playerId, amounts);
|
|
2594
|
+
throw new Error(
|
|
2595
|
+
`spendPlayerResources: player '${playerId}' cannot afford ${JSON.stringify(
|
|
2596
|
+
missing
|
|
2597
|
+
)}. Check canAfford in your validate step first.`
|
|
2598
|
+
);
|
|
2599
|
+
}
|
|
2600
|
+
const prev = perPlayerGet(
|
|
2601
|
+
table.resources,
|
|
2602
|
+
playerId
|
|
2603
|
+
) ?? {};
|
|
2604
|
+
const next = { ...prev };
|
|
2605
|
+
forEachResourceEntry(amounts, (resourceId, amount) => {
|
|
2606
|
+
if (amount < 0) {
|
|
2607
|
+
throw new Error(
|
|
2608
|
+
`spendPlayerResources: negative amount for resource '${resourceId}'. Pass positive amounts \u2014 the op deducts them from the player.`
|
|
2609
|
+
);
|
|
2610
|
+
}
|
|
2611
|
+
next[resourceId] = Math.max(0, (next[resourceId] ?? 0) - amount);
|
|
2612
|
+
});
|
|
2613
|
+
return withPlayerResources(table, playerId, next);
|
|
2923
2614
|
}
|
|
2924
|
-
function
|
|
2925
|
-
|
|
2615
|
+
function transferPlayerResources(table, fromPlayerId, toPlayerId, amounts) {
|
|
2616
|
+
const afterSpend = spendPlayerResources(table, fromPlayerId, amounts);
|
|
2617
|
+
return addPlayerResources(afterSpend, toPlayerId, amounts);
|
|
2926
2618
|
}
|
|
2927
|
-
function
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2619
|
+
function setPlayerResource(table, playerId, resourceId, amount) {
|
|
2620
|
+
if (!Number.isFinite(amount) || amount < 0) {
|
|
2621
|
+
throw new Error(
|
|
2622
|
+
`setPlayerResource: amount must be a non-negative finite number, got ${amount}.`
|
|
2623
|
+
);
|
|
2624
|
+
}
|
|
2625
|
+
const prev = perPlayerGet(
|
|
2626
|
+
table.resources,
|
|
2627
|
+
playerId
|
|
2628
|
+
) ?? {};
|
|
2629
|
+
return withPlayerResources(table, playerId, {
|
|
2630
|
+
...prev,
|
|
2631
|
+
[resourceId]: amount
|
|
2632
|
+
});
|
|
2933
2633
|
}
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
(
|
|
2634
|
+
|
|
2635
|
+
// src/reducer/table/component-mutations.ts
|
|
2636
|
+
function reindexSpaceOccupants(table, boardId, spaceId) {
|
|
2637
|
+
getComponentsOnSpace(table, boardId, spaceId).forEach(
|
|
2638
|
+
(componentId, index) => {
|
|
2639
|
+
const location = table.componentLocations[componentId];
|
|
2640
|
+
if (location?.type === "OnSpace") {
|
|
2641
|
+
table.componentLocations[componentId] = {
|
|
2642
|
+
...location,
|
|
2643
|
+
position: index
|
|
2644
|
+
};
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2939
2647
|
);
|
|
2940
2648
|
}
|
|
2941
|
-
function
|
|
2942
|
-
|
|
2649
|
+
function reindexContainerOccupants(table, boardId, containerId) {
|
|
2650
|
+
getComponentsInContainer(table, boardId, containerId).forEach(
|
|
2651
|
+
(componentId, index) => {
|
|
2652
|
+
const location = table.componentLocations[componentId];
|
|
2653
|
+
if (location?.type === "InContainer") {
|
|
2654
|
+
table.componentLocations[componentId] = {
|
|
2655
|
+
...location,
|
|
2656
|
+
position: index
|
|
2657
|
+
};
|
|
2658
|
+
}
|
|
2659
|
+
}
|
|
2660
|
+
);
|
|
2661
|
+
}
|
|
2662
|
+
function reindexEdgeOccupants(table, boardId, edgeId) {
|
|
2663
|
+
orderedComponentIdsForLocation(
|
|
2943
2664
|
table,
|
|
2944
2665
|
(location) => location.type === "OnEdge" && location.boardId === boardId && location.edgeId === edgeId
|
|
2945
|
-
)
|
|
2666
|
+
).forEach((componentId, index) => {
|
|
2667
|
+
const location = table.componentLocations[componentId];
|
|
2668
|
+
if (location?.type === "OnEdge") {
|
|
2669
|
+
table.componentLocations[componentId] = {
|
|
2670
|
+
...location,
|
|
2671
|
+
position: index
|
|
2672
|
+
};
|
|
2673
|
+
}
|
|
2674
|
+
});
|
|
2946
2675
|
}
|
|
2947
|
-
function
|
|
2948
|
-
|
|
2676
|
+
function reindexVertexOccupants(table, boardId, vertexId) {
|
|
2677
|
+
orderedComponentIdsForLocation(
|
|
2949
2678
|
table,
|
|
2950
2679
|
(location) => location.type === "OnVertex" && location.boardId === boardId && location.vertexId === vertexId
|
|
2951
|
-
)
|
|
2680
|
+
).forEach((componentId, index) => {
|
|
2681
|
+
const location = table.componentLocations[componentId];
|
|
2682
|
+
if (location?.type === "OnVertex") {
|
|
2683
|
+
table.componentLocations[componentId] = {
|
|
2684
|
+
...location,
|
|
2685
|
+
position: index
|
|
2686
|
+
};
|
|
2687
|
+
}
|
|
2688
|
+
});
|
|
2689
|
+
}
|
|
2690
|
+
function reindexSlotOccupants(table, host, slotId) {
|
|
2691
|
+
orderedComponentIdsForLocation(
|
|
2692
|
+
table,
|
|
2693
|
+
(location) => location.type === "InSlot" && location.host.kind === host.kind && location.host.id === host.id && location.slotId === slotId
|
|
2694
|
+
).forEach((componentId, index) => {
|
|
2695
|
+
const location = table.componentLocations[componentId];
|
|
2696
|
+
if (location?.type === "InSlot") {
|
|
2697
|
+
table.componentLocations[componentId] = {
|
|
2698
|
+
...location,
|
|
2699
|
+
position: index
|
|
2700
|
+
};
|
|
2701
|
+
}
|
|
2702
|
+
});
|
|
2703
|
+
}
|
|
2704
|
+
function removeComponentFromCurrentLocation(table, componentId) {
|
|
2705
|
+
const currentLocation = table.componentLocations[componentId];
|
|
2706
|
+
if (!currentLocation) {
|
|
2707
|
+
return;
|
|
2708
|
+
}
|
|
2709
|
+
if (currentLocation.type === "InDeck") {
|
|
2710
|
+
const nextCards = ensureArray(table.decks[currentLocation.deckId]).filter(
|
|
2711
|
+
(candidate) => candidate !== componentId
|
|
2712
|
+
);
|
|
2713
|
+
syncSharedZoneWithDeck(
|
|
2714
|
+
table,
|
|
2715
|
+
currentLocation.deckId,
|
|
2716
|
+
nextCards
|
|
2717
|
+
);
|
|
2718
|
+
nextCards.forEach((cardId, index) => {
|
|
2719
|
+
const location = table.componentLocations[cardId];
|
|
2720
|
+
if (location?.type === "InDeck") {
|
|
2721
|
+
table.componentLocations[cardId] = {
|
|
2722
|
+
...location,
|
|
2723
|
+
position: index
|
|
2724
|
+
};
|
|
2725
|
+
}
|
|
2726
|
+
});
|
|
2727
|
+
return;
|
|
2728
|
+
}
|
|
2729
|
+
if (currentLocation.type === "InHand") {
|
|
2730
|
+
const nextCards = ensureArray(
|
|
2731
|
+
ppRead(table.hands[currentLocation.handId], currentLocation.playerId)
|
|
2732
|
+
).filter((candidate) => candidate !== componentId);
|
|
2733
|
+
syncPlayerZoneWithHand(
|
|
2734
|
+
table,
|
|
2735
|
+
currentLocation.handId,
|
|
2736
|
+
currentLocation.playerId,
|
|
2737
|
+
nextCards
|
|
2738
|
+
);
|
|
2739
|
+
nextCards.forEach((cardId, index) => {
|
|
2740
|
+
const location = table.componentLocations[cardId];
|
|
2741
|
+
if (location?.type === "InHand") {
|
|
2742
|
+
table.componentLocations[cardId] = {
|
|
2743
|
+
...location,
|
|
2744
|
+
position: index
|
|
2745
|
+
};
|
|
2746
|
+
}
|
|
2747
|
+
});
|
|
2748
|
+
return;
|
|
2749
|
+
}
|
|
2750
|
+
if (currentLocation.type === "OnSpace") {
|
|
2751
|
+
delete table.componentLocations[componentId];
|
|
2752
|
+
reindexSpaceOccupants(
|
|
2753
|
+
table,
|
|
2754
|
+
currentLocation.boardId,
|
|
2755
|
+
currentLocation.spaceId
|
|
2756
|
+
);
|
|
2757
|
+
return;
|
|
2758
|
+
}
|
|
2759
|
+
if (currentLocation.type === "InZone") {
|
|
2760
|
+
if (currentLocation.zoneId in table.zones.shared) {
|
|
2761
|
+
const nextComponents = ensureArray(
|
|
2762
|
+
table.zones.shared[currentLocation.zoneId]
|
|
2763
|
+
).filter((candidate) => candidate !== componentId);
|
|
2764
|
+
syncSharedZoneWithDeck(
|
|
2765
|
+
table,
|
|
2766
|
+
currentLocation.zoneId,
|
|
2767
|
+
nextComponents
|
|
2768
|
+
);
|
|
2769
|
+
nextComponents.forEach((currentComponentId, index) => {
|
|
2770
|
+
const location = table.componentLocations[currentComponentId];
|
|
2771
|
+
if (location?.type === "InZone") {
|
|
2772
|
+
table.componentLocations[currentComponentId] = {
|
|
2773
|
+
...location,
|
|
2774
|
+
position: index
|
|
2775
|
+
};
|
|
2776
|
+
}
|
|
2777
|
+
});
|
|
2778
|
+
}
|
|
2779
|
+
delete table.componentLocations[componentId];
|
|
2780
|
+
return;
|
|
2781
|
+
}
|
|
2782
|
+
if (currentLocation.type === "InContainer") {
|
|
2783
|
+
delete table.componentLocations[componentId];
|
|
2784
|
+
reindexContainerOccupants(
|
|
2785
|
+
table,
|
|
2786
|
+
currentLocation.boardId,
|
|
2787
|
+
currentLocation.containerId
|
|
2788
|
+
);
|
|
2789
|
+
return;
|
|
2790
|
+
}
|
|
2791
|
+
if (currentLocation.type === "OnEdge") {
|
|
2792
|
+
delete table.componentLocations[componentId];
|
|
2793
|
+
reindexEdgeOccupants(
|
|
2794
|
+
table,
|
|
2795
|
+
currentLocation.boardId,
|
|
2796
|
+
currentLocation.edgeId
|
|
2797
|
+
);
|
|
2798
|
+
return;
|
|
2799
|
+
}
|
|
2800
|
+
if (currentLocation.type === "OnVertex") {
|
|
2801
|
+
delete table.componentLocations[componentId];
|
|
2802
|
+
reindexVertexOccupants(
|
|
2803
|
+
table,
|
|
2804
|
+
currentLocation.boardId,
|
|
2805
|
+
currentLocation.vertexId
|
|
2806
|
+
);
|
|
2807
|
+
return;
|
|
2808
|
+
}
|
|
2809
|
+
if (currentLocation.type === "InSlot") {
|
|
2810
|
+
delete table.componentLocations[componentId];
|
|
2811
|
+
reindexSlotOccupants(table, currentLocation.host, currentLocation.slotId);
|
|
2812
|
+
return;
|
|
2813
|
+
}
|
|
2814
|
+
delete table.componentLocations[componentId];
|
|
2952
2815
|
}
|
|
2953
2816
|
function moveComponentToSpace(table, componentId, boardId, spaceId) {
|
|
2954
2817
|
const nextTable = cloneRuntimeTable(table);
|
|
@@ -2979,37 +2842,176 @@ function moveComponentToContainer(table, componentId, boardId, containerId) {
|
|
|
2979
2842
|
};
|
|
2980
2843
|
return nextTable;
|
|
2981
2844
|
}
|
|
2982
|
-
function moveComponentToDetached(table, componentId) {
|
|
2845
|
+
function moveComponentToDetached(table, componentId) {
|
|
2846
|
+
const nextTable = cloneRuntimeTable(table);
|
|
2847
|
+
removeComponentFromCurrentLocation(nextTable, componentId);
|
|
2848
|
+
nextTable.componentLocations[componentId] = { type: "Detached" };
|
|
2849
|
+
return nextTable;
|
|
2850
|
+
}
|
|
2851
|
+
function moveComponentToEdge(table, componentId, boardId, edgeId) {
|
|
2852
|
+
const nextTable = cloneRuntimeTable(table);
|
|
2853
|
+
getEdge(nextTable, boardId, edgeId);
|
|
2854
|
+
const position = getComponentsOnEdge(nextTable, boardId, edgeId).length;
|
|
2855
|
+
removeComponentFromCurrentLocation(nextTable, componentId);
|
|
2856
|
+
nextTable.componentLocations[componentId] = {
|
|
2857
|
+
type: "OnEdge",
|
|
2858
|
+
boardId,
|
|
2859
|
+
edgeId,
|
|
2860
|
+
position
|
|
2861
|
+
};
|
|
2862
|
+
return nextTable;
|
|
2863
|
+
}
|
|
2864
|
+
function moveComponentToVertex(table, componentId, boardId, vertexId) {
|
|
2865
|
+
const nextTable = cloneRuntimeTable(table);
|
|
2866
|
+
getVertex(nextTable, boardId, vertexId);
|
|
2867
|
+
const position = getComponentsOnVertex(nextTable, boardId, vertexId).length;
|
|
2868
|
+
removeComponentFromCurrentLocation(nextTable, componentId);
|
|
2869
|
+
nextTable.componentLocations[componentId] = {
|
|
2870
|
+
type: "OnVertex",
|
|
2871
|
+
boardId,
|
|
2872
|
+
vertexId,
|
|
2873
|
+
position
|
|
2874
|
+
};
|
|
2875
|
+
return nextTable;
|
|
2876
|
+
}
|
|
2877
|
+
|
|
2878
|
+
// src/reducer/table/card-mutations.ts
|
|
2879
|
+
function shufflePlayerZoneCards(table, zoneId, playerId, nextCards) {
|
|
2880
|
+
if (nextCards === void 0) {
|
|
2881
|
+
const fromZone = ppRead(
|
|
2882
|
+
table.zones.perPlayer[zoneId] ?? table.hands[zoneId],
|
|
2883
|
+
playerId
|
|
2884
|
+
);
|
|
2885
|
+
return [...ensureArray(fromZone)];
|
|
2886
|
+
}
|
|
2887
|
+
table.hands[zoneId] = ppWrite(table.hands[zoneId], playerId, [
|
|
2888
|
+
...nextCards
|
|
2889
|
+
]);
|
|
2890
|
+
table.zones.perPlayer[zoneId] = ppWrite(
|
|
2891
|
+
table.zones.perPlayer[zoneId],
|
|
2892
|
+
playerId,
|
|
2893
|
+
[...nextCards]
|
|
2894
|
+
);
|
|
2895
|
+
return [...nextCards];
|
|
2896
|
+
}
|
|
2897
|
+
function appendToDeck(table, deckId, cardId, playedBy = null, position = "bottom") {
|
|
2898
|
+
const nextTable = cloneRuntimeTable(table);
|
|
2899
|
+
assertZoneScope(
|
|
2900
|
+
nextTable,
|
|
2901
|
+
deckId,
|
|
2902
|
+
"shared",
|
|
2903
|
+
"addCardToSharedZone",
|
|
2904
|
+
"zoneId"
|
|
2905
|
+
);
|
|
2906
|
+
const deckCards = [
|
|
2907
|
+
...ensureArray(nextTable.decks[deckId])
|
|
2908
|
+
];
|
|
2909
|
+
assertCardAllowedInZone(nextTable, deckId, cardId);
|
|
2910
|
+
if (position === "top") {
|
|
2911
|
+
deckCards.unshift(cardId);
|
|
2912
|
+
} else {
|
|
2913
|
+
deckCards.push(cardId);
|
|
2914
|
+
}
|
|
2915
|
+
syncSharedZoneWithDeck(nextTable, deckId, deckCards);
|
|
2916
|
+
for (const [index, currentCardId] of deckCards.entries()) {
|
|
2917
|
+
if (currentCardId === cardId) {
|
|
2918
|
+
nextTable.componentLocations[currentCardId] = {
|
|
2919
|
+
type: "InDeck",
|
|
2920
|
+
deckId,
|
|
2921
|
+
playedBy,
|
|
2922
|
+
position: index
|
|
2923
|
+
};
|
|
2924
|
+
continue;
|
|
2925
|
+
}
|
|
2926
|
+
const existing = nextTable.componentLocations[currentCardId];
|
|
2927
|
+
nextTable.componentLocations[currentCardId] = {
|
|
2928
|
+
type: "InDeck",
|
|
2929
|
+
deckId,
|
|
2930
|
+
playedBy: existing?.type === "InDeck" ? existing.playedBy : null,
|
|
2931
|
+
position: index
|
|
2932
|
+
};
|
|
2933
|
+
}
|
|
2934
|
+
nextTable.ownerOfCard[cardId] = playedBy;
|
|
2935
|
+
nextTable.visibility[cardId] = {
|
|
2936
|
+
faceUp: true
|
|
2937
|
+
};
|
|
2938
|
+
return nextTable;
|
|
2939
|
+
}
|
|
2940
|
+
function removeFromDeck(table, deckId, cardId) {
|
|
2983
2941
|
const nextTable = cloneRuntimeTable(table);
|
|
2984
|
-
|
|
2985
|
-
|
|
2942
|
+
assertZoneScope(
|
|
2943
|
+
nextTable,
|
|
2944
|
+
deckId,
|
|
2945
|
+
"shared",
|
|
2946
|
+
"removeCardFromSharedZone",
|
|
2947
|
+
"zoneId"
|
|
2948
|
+
);
|
|
2949
|
+
const remaining = ensureArray(nextTable.decks[deckId]).filter(
|
|
2950
|
+
(candidate) => candidate !== cardId
|
|
2951
|
+
);
|
|
2952
|
+
syncSharedZoneWithDeck(nextTable, deckId, remaining);
|
|
2953
|
+
for (const [index, currentCardId] of remaining.entries()) {
|
|
2954
|
+
const currentLocation = nextTable.componentLocations[currentCardId];
|
|
2955
|
+
if (currentLocation?.type === "InDeck") {
|
|
2956
|
+
nextTable.componentLocations[currentCardId] = {
|
|
2957
|
+
...currentLocation,
|
|
2958
|
+
position: index
|
|
2959
|
+
};
|
|
2960
|
+
}
|
|
2961
|
+
}
|
|
2986
2962
|
return nextTable;
|
|
2987
2963
|
}
|
|
2988
|
-
function
|
|
2989
|
-
const
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
type: "OnEdge",
|
|
2995
|
-
boardId,
|
|
2996
|
-
edgeId,
|
|
2997
|
-
position
|
|
2998
|
-
};
|
|
2999
|
-
return nextTable;
|
|
2964
|
+
function computeVisibilityForPlayerZone(table, zoneId, playerId) {
|
|
2965
|
+
const mode = table.handVisibility[zoneId];
|
|
2966
|
+
if (mode === "all" || mode === "public") {
|
|
2967
|
+
return { faceUp: true };
|
|
2968
|
+
}
|
|
2969
|
+
return { faceUp: false, visibleTo: [playerId] };
|
|
3000
2970
|
}
|
|
3001
|
-
function
|
|
3002
|
-
const nextTable = cloneRuntimeTable(table);
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
2971
|
+
function moveFromHandToDeck(options) {
|
|
2972
|
+
const nextTable = cloneRuntimeTable(options.table);
|
|
2973
|
+
assertZoneScope(
|
|
2974
|
+
nextTable,
|
|
2975
|
+
options.handId,
|
|
2976
|
+
"perPlayer",
|
|
2977
|
+
"moveCardFromPlayerZoneToSharedZone",
|
|
2978
|
+
"fromZoneId"
|
|
2979
|
+
);
|
|
2980
|
+
assertZoneScope(
|
|
2981
|
+
nextTable,
|
|
2982
|
+
options.deckId,
|
|
2983
|
+
"shared",
|
|
2984
|
+
"moveCardFromPlayerZoneToSharedZone",
|
|
2985
|
+
"toZoneId"
|
|
2986
|
+
);
|
|
2987
|
+
const currentHand = ensureArray(
|
|
2988
|
+
ppRead(nextTable.hands[options.handId], options.playerId)
|
|
2989
|
+
).filter((candidate) => candidate !== options.cardId);
|
|
2990
|
+
syncPlayerZoneWithHand(
|
|
2991
|
+
nextTable,
|
|
2992
|
+
options.handId,
|
|
2993
|
+
options.playerId,
|
|
2994
|
+
currentHand
|
|
2995
|
+
);
|
|
2996
|
+
for (const [index, currentCardId] of currentHand.entries()) {
|
|
2997
|
+
nextTable.componentLocations[currentCardId] = {
|
|
2998
|
+
type: "InHand",
|
|
2999
|
+
handId: options.handId,
|
|
3000
|
+
playerId: options.playerId,
|
|
3001
|
+
position: index
|
|
3002
|
+
};
|
|
3003
|
+
}
|
|
3004
|
+
nextTable.ownerOfCard[options.cardId] = options.playedBy ?? options.playerId;
|
|
3005
|
+
nextTable.visibility[options.cardId] = {
|
|
3006
|
+
faceUp: true
|
|
3011
3007
|
};
|
|
3012
|
-
return
|
|
3008
|
+
return appendToDeck(
|
|
3009
|
+
nextTable,
|
|
3010
|
+
options.deckId,
|
|
3011
|
+
options.cardId,
|
|
3012
|
+
options.playedBy ?? options.playerId,
|
|
3013
|
+
options.position ?? "bottom"
|
|
3014
|
+
);
|
|
3013
3015
|
}
|
|
3014
3016
|
function moveCardFromPlayerZoneToSharedZone(options) {
|
|
3015
3017
|
return moveFromHandToDeck({
|
|
@@ -3264,6 +3266,23 @@ function dealCardsFromDeckToHand(table, fromZoneId, playerId, toZoneId, count) {
|
|
|
3264
3266
|
return nextTable;
|
|
3265
3267
|
}
|
|
3266
3268
|
|
|
3269
|
+
// src/reducer/table/phase-state.ts
|
|
3270
|
+
function setActivePlayers(state, activePlayers) {
|
|
3271
|
+
return {
|
|
3272
|
+
...state,
|
|
3273
|
+
flow: {
|
|
3274
|
+
...state.flow,
|
|
3275
|
+
activePlayers
|
|
3276
|
+
}
|
|
3277
|
+
};
|
|
3278
|
+
}
|
|
3279
|
+
function setPhaseState(state, phaseState) {
|
|
3280
|
+
return {
|
|
3281
|
+
...state,
|
|
3282
|
+
phase: phaseState
|
|
3283
|
+
};
|
|
3284
|
+
}
|
|
3285
|
+
|
|
3267
3286
|
// src/reducer/rng.ts
|
|
3268
3287
|
function nextRandomInt(bound, rng) {
|
|
3269
3288
|
if (bound <= 0) {
|
|
@@ -4904,33 +4923,7 @@ function createTrustedInstructionRunner(scope, interactions, lifecycle) {
|
|
|
4904
4923
|
};
|
|
4905
4924
|
}
|
|
4906
4925
|
|
|
4907
|
-
// src/reducer/
|
|
4908
|
-
function formatIssue(label, issue) {
|
|
4909
|
-
const path = issue.path.map(
|
|
4910
|
-
(segment) => typeof segment === "symbol" ? segment.toString() : String(segment)
|
|
4911
|
-
).join(".");
|
|
4912
|
-
return `${path || label}: ${issue.message}`;
|
|
4913
|
-
}
|
|
4914
|
-
function safeParseOrThrow(schema, value, label) {
|
|
4915
|
-
const parsed = schema.safeParse(value);
|
|
4916
|
-
if (!parsed.success) {
|
|
4917
|
-
const message = parsed.error.issues.map((issue) => formatIssue(label, issue)).join("; ");
|
|
4918
|
-
throw new Error(message || `Invalid ${label}`);
|
|
4919
|
-
}
|
|
4920
|
-
return parsed.data;
|
|
4921
|
-
}
|
|
4922
|
-
|
|
4923
|
-
// src/reducer/bundle/trusted/interaction-types.ts
|
|
4924
|
-
function makeValidationError(errorCode, message) {
|
|
4925
|
-
return {
|
|
4926
|
-
valid: false,
|
|
4927
|
-
errorCode,
|
|
4928
|
-
message
|
|
4929
|
-
};
|
|
4930
|
-
}
|
|
4931
|
-
|
|
4932
|
-
// src/reducer/bundle/trusted/interaction-collectors.ts
|
|
4933
|
-
var MAX_EAGER_DEPENDENT_DOMAIN_CASES = 64;
|
|
4926
|
+
// src/reducer/bundle/trusted/collector-introspection.ts
|
|
4934
4927
|
function collectTargetDomainMetadata(collector) {
|
|
4935
4928
|
switch (collector.kind) {
|
|
4936
4929
|
case "card": {
|
|
@@ -4952,389 +4945,105 @@ function collectTargetDomainMetadata(collector) {
|
|
|
4952
4945
|
valueKind: meta.valueKind
|
|
4953
4946
|
};
|
|
4954
4947
|
}
|
|
4955
|
-
default:
|
|
4956
|
-
return {};
|
|
4957
|
-
}
|
|
4958
|
-
}
|
|
4959
|
-
function withSelection(domain, collector) {
|
|
4960
|
-
if (!collector.selection) return domain;
|
|
4961
|
-
return { ...domain, selection: collector.selection };
|
|
4962
|
-
}
|
|
4963
|
-
function lazyTargetDomainFromCollectorMetadata(key, collector, dependencies) {
|
|
4964
|
-
const metadata = collectTargetDomainMetadata(collector);
|
|
4965
|
-
if (collector.kind === "card") {
|
|
4966
|
-
return withSelection(
|
|
4967
|
-
{
|
|
4968
|
-
type: "cardTarget",
|
|
4969
|
-
projection: "lazy",
|
|
4970
|
-
targetKind: "card",
|
|
4971
|
-
zoneIds: metadata.zoneIds ?? (metadata.zoneId === void 0 ? [] : [metadata.zoneId]),
|
|
4972
|
-
dependencies: {
|
|
4973
|
-
mode: "lazy",
|
|
4974
|
-
dependsOn: dependencies,
|
|
4975
|
-
resolver: { inputKey: key }
|
|
4976
|
-
}
|
|
4977
|
-
},
|
|
4978
|
-
collector
|
|
4979
|
-
);
|
|
4980
|
-
}
|
|
4981
|
-
if (collector.kind === "board-edge" || collector.kind === "board-space" || collector.kind === "board-tile" || collector.kind === "board-vertex") {
|
|
4982
|
-
return withSelection(
|
|
4983
|
-
{
|
|
4984
|
-
type: "boardTarget",
|
|
4985
|
-
projection: "lazy",
|
|
4986
|
-
targetKind: metadata.targetKind ?? collector.kind.replace("board-", ""),
|
|
4987
|
-
boardId: metadata.boardId ?? "",
|
|
4988
|
-
...metadata.valueKind ? { valueKind: metadata.valueKind } : {},
|
|
4989
|
-
dependencies: {
|
|
4990
|
-
mode: "lazy",
|
|
4991
|
-
dependsOn: dependencies,
|
|
4992
|
-
resolver: { inputKey: key }
|
|
4993
|
-
}
|
|
4994
|
-
},
|
|
4995
|
-
collector
|
|
4996
|
-
);
|
|
4997
|
-
}
|
|
4998
|
-
return null;
|
|
4999
|
-
}
|
|
5000
|
-
function finiteValuesForDependency(key, domain) {
|
|
5001
|
-
if (!domain) {
|
|
5002
|
-
throw new Error(
|
|
5003
|
-
`Interaction input '${key}' is declared as a dependency before it has a projected domain.`
|
|
5004
|
-
);
|
|
5005
|
-
}
|
|
5006
|
-
if (domain.type === "cardTarget" || domain.type === "boardTarget") {
|
|
5007
|
-
if (domain.projection !== "resolved") {
|
|
5008
|
-
throw new Error(
|
|
5009
|
-
`Interaction input '${key}' cannot be used as a dependency because its target domain is not finite.`
|
|
5010
|
-
);
|
|
5011
|
-
}
|
|
5012
|
-
return [...domain.eligibleTargets];
|
|
5013
|
-
}
|
|
5014
|
-
if (domain.type === "choice") {
|
|
5015
|
-
return domain.choices.flatMap(
|
|
5016
|
-
(choice) => choice.value === null ? [] : [choice.value]
|
|
5017
|
-
);
|
|
5018
|
-
}
|
|
5019
|
-
throw new Error(
|
|
5020
|
-
`Interaction input '${key}' cannot be used as a dependency. V1 supports finite target and choice dependencies only.`
|
|
5021
|
-
);
|
|
5022
|
-
}
|
|
5023
|
-
function cartesianDependencyTuples(dependencies, domainsByKey) {
|
|
5024
|
-
return dependencies.reduce(
|
|
5025
|
-
(tuples, key) => {
|
|
5026
|
-
const values = finiteValuesForDependency(key, domainsByKey[key]);
|
|
5027
|
-
return tuples.flatMap(
|
|
5028
|
-
(tuple) => values.map((value) => ({ ...tuple, [key]: value }))
|
|
5029
|
-
);
|
|
5030
|
-
},
|
|
5031
|
-
[{}]
|
|
5032
|
-
);
|
|
5033
|
-
}
|
|
5034
|
-
function withoutDependentProjection(domain) {
|
|
5035
|
-
const { dependencies: _dependencies, ...rest } = domain;
|
|
5036
|
-
return rest;
|
|
5037
|
-
}
|
|
5038
|
-
function toLazyTargetDomain(key, domain, dependencies) {
|
|
5039
|
-
if (domain.type === "cardTarget") {
|
|
5040
|
-
return {
|
|
5041
|
-
type: "cardTarget",
|
|
5042
|
-
projection: "lazy",
|
|
5043
|
-
targetKind: "card",
|
|
5044
|
-
zoneIds: domain.zoneIds,
|
|
5045
|
-
...domain.selection ? { selection: domain.selection } : {},
|
|
5046
|
-
dependencies: {
|
|
5047
|
-
mode: "lazy",
|
|
5048
|
-
dependsOn: dependencies,
|
|
5049
|
-
resolver: { inputKey: key }
|
|
5050
|
-
}
|
|
5051
|
-
};
|
|
5052
|
-
}
|
|
5053
|
-
if (domain.type === "boardTarget") {
|
|
5054
|
-
return {
|
|
5055
|
-
type: "boardTarget",
|
|
5056
|
-
projection: "lazy",
|
|
5057
|
-
targetKind: domain.targetKind,
|
|
5058
|
-
boardId: domain.boardId,
|
|
5059
|
-
...domain.valueKind ? { valueKind: domain.valueKind } : {},
|
|
5060
|
-
...domain.selection ? { selection: domain.selection } : {},
|
|
5061
|
-
dependencies: {
|
|
5062
|
-
mode: "lazy",
|
|
5063
|
-
dependsOn: dependencies,
|
|
5064
|
-
resolver: { inputKey: key }
|
|
5065
|
-
}
|
|
5066
|
-
};
|
|
4948
|
+
default:
|
|
4949
|
+
return {};
|
|
5067
4950
|
}
|
|
5068
|
-
return null;
|
|
5069
|
-
}
|
|
5070
|
-
function dependencyCaseCount(dependencies, domainsByKey) {
|
|
5071
|
-
return dependencies.map((key) => finiteValuesForDependency(key, domainsByKey[key]).length).reduce((total, count) => total * count, 1);
|
|
5072
|
-
}
|
|
5073
|
-
function unsupportedDefaultInputError(key, collector) {
|
|
5074
|
-
return new Error(
|
|
5075
|
-
`Interaction input '${key}' uses a '${collector.kind}' collector without a default-renderable domain or target metadata. Use formInput.choice(...), formInput.choiceList(...), formInput.number(...), formInput.resourceMap(...), cardInput(...), or boardInput(...). For custom payloads, use a custom interaction surface with paramsSchema instead of the default InteractionForm.`
|
|
5076
|
-
);
|
|
5077
4951
|
}
|
|
5078
4952
|
function interactionInputsOf(interaction) {
|
|
5079
4953
|
return interaction.inputs;
|
|
5080
4954
|
}
|
|
5081
|
-
function
|
|
4955
|
+
function collectFirstCardZoneId(interaction) {
|
|
5082
4956
|
const collectors = interactionInputsOf(interaction);
|
|
5083
|
-
const
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
for (const [key, collector] of Object.entries(collectors)) {
|
|
5089
|
-
if (!collector.eligibleTargets) continue;
|
|
5090
|
-
const cacheKey = options.eligibleTargetCachePrefix ? `${options.eligibleTargetCachePrefix}:${key}` : null;
|
|
5091
|
-
const cached = cacheKey ? options.eligibleTargetCache?.get(cacheKey) : void 0;
|
|
5092
|
-
if (cached) {
|
|
5093
|
-
result[key] = cached;
|
|
5094
|
-
continue;
|
|
5095
|
-
}
|
|
5096
|
-
const targets = collector.eligibleTargets(
|
|
5097
|
-
domainState,
|
|
5098
|
-
playerId,
|
|
5099
|
-
queries()
|
|
5100
|
-
);
|
|
5101
|
-
const resolved = Array.from(targets).map(
|
|
5102
|
-
(t) => String(t)
|
|
5103
|
-
);
|
|
5104
|
-
result[key] = resolved;
|
|
5105
|
-
if (cacheKey) {
|
|
5106
|
-
options.eligibleTargetCache?.set(cacheKey, resolved);
|
|
4957
|
+
for (const collector of Object.values(collectors)) {
|
|
4958
|
+
if (collector.kind === "card") {
|
|
4959
|
+
if (collector.meta.zoneId.length > 0) {
|
|
4960
|
+
return collector.meta.zoneId;
|
|
4961
|
+
}
|
|
5107
4962
|
}
|
|
5108
4963
|
}
|
|
5109
|
-
return
|
|
4964
|
+
return void 0;
|
|
5110
4965
|
}
|
|
5111
|
-
function
|
|
4966
|
+
function collectCardZoneIds(interaction) {
|
|
5112
4967
|
const collectors = interactionInputsOf(interaction);
|
|
5113
|
-
|
|
5114
|
-
const
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
const derived = () => derivedLazy ??= createDerivedResolver(domainState, { q: queries() });
|
|
5119
|
-
const result = {};
|
|
5120
|
-
for (const [key, collector] of Object.entries(collectors)) {
|
|
5121
|
-
if (collector.kind === "rng") {
|
|
5122
|
-
continue;
|
|
5123
|
-
}
|
|
5124
|
-
if (collector.kind === "prompt") {
|
|
5125
|
-
const optionFactory = collector.meta?.options;
|
|
5126
|
-
if (!optionFactory) continue;
|
|
5127
|
-
result[key] = {
|
|
5128
|
-
type: "choice",
|
|
5129
|
-
choices: optionFactory(domainState, playerId, queries()).map(
|
|
5130
|
-
(option) => ({
|
|
5131
|
-
value: String(option.id),
|
|
5132
|
-
label: option.label ?? String(option.id),
|
|
5133
|
-
...(() => {
|
|
5134
|
-
const issue = collector.validateTarget?.(
|
|
5135
|
-
domainState,
|
|
5136
|
-
playerId,
|
|
5137
|
-
queries(),
|
|
5138
|
-
String(option.id)
|
|
5139
|
-
);
|
|
5140
|
-
return issue ? {
|
|
5141
|
-
disabled: true,
|
|
5142
|
-
disabledReason: issue.message ?? issue.errorCode
|
|
5143
|
-
} : {};
|
|
5144
|
-
})()
|
|
5145
|
-
})
|
|
5146
|
-
)
|
|
5147
|
-
};
|
|
5148
|
-
continue;
|
|
5149
|
-
}
|
|
5150
|
-
if (collector.domain) {
|
|
5151
|
-
const domainProjector = collector.domain;
|
|
5152
|
-
const dependencies = collector.dependsOn ?? [];
|
|
5153
|
-
if (options.includeEligibleTargets === false && !Object.prototype.hasOwnProperty.call(eligibleTargets, key)) {
|
|
5154
|
-
const lazyDomain2 = lazyTargetDomainFromCollectorMetadata(
|
|
5155
|
-
key,
|
|
5156
|
-
collector,
|
|
5157
|
-
dependencies
|
|
5158
|
-
);
|
|
5159
|
-
if (lazyDomain2) {
|
|
5160
|
-
result[key] = lazyDomain2;
|
|
5161
|
-
continue;
|
|
5162
|
-
}
|
|
5163
|
-
}
|
|
5164
|
-
const baseDomain = withSelection(
|
|
5165
|
-
domainProjector(
|
|
5166
|
-
domainState,
|
|
5167
|
-
playerId,
|
|
5168
|
-
queries(),
|
|
5169
|
-
derived(),
|
|
5170
|
-
{}
|
|
5171
|
-
),
|
|
5172
|
-
collector
|
|
5173
|
-
);
|
|
5174
|
-
if (dependencies.length === 0) {
|
|
5175
|
-
result[key] = baseDomain;
|
|
5176
|
-
continue;
|
|
5177
|
-
}
|
|
5178
|
-
const caseCount = dependencyCaseCount(dependencies, result);
|
|
5179
|
-
const lazyDomain = caseCount > MAX_EAGER_DEPENDENT_DOMAIN_CASES ? toLazyTargetDomain(key, baseDomain, dependencies) : null;
|
|
5180
|
-
if (lazyDomain) {
|
|
5181
|
-
result[key] = lazyDomain;
|
|
5182
|
-
continue;
|
|
4968
|
+
const zoneIds = /* @__PURE__ */ new Set();
|
|
4969
|
+
for (const collector of Object.values(collectors)) {
|
|
4970
|
+
if (collector.kind === "card") {
|
|
4971
|
+
for (const zoneId of collector.meta.zoneIds ?? [collector.meta.zoneId]) {
|
|
4972
|
+
if (zoneId.length > 0) zoneIds.add(zoneId);
|
|
5183
4973
|
}
|
|
5184
|
-
const dependentCases = cartesianDependencyTuples(
|
|
5185
|
-
dependencies,
|
|
5186
|
-
result
|
|
5187
|
-
).map((values) => ({
|
|
5188
|
-
when: values,
|
|
5189
|
-
domain: withoutDependentProjection(
|
|
5190
|
-
withSelection(
|
|
5191
|
-
domainProjector(
|
|
5192
|
-
domainState,
|
|
5193
|
-
playerId,
|
|
5194
|
-
queries(),
|
|
5195
|
-
derived(),
|
|
5196
|
-
values
|
|
5197
|
-
),
|
|
5198
|
-
collector
|
|
5199
|
-
)
|
|
5200
|
-
)
|
|
5201
|
-
}));
|
|
5202
|
-
result[key] = {
|
|
5203
|
-
...baseDomain,
|
|
5204
|
-
dependencies: {
|
|
5205
|
-
mode: "eager",
|
|
5206
|
-
dependentCases
|
|
5207
|
-
}
|
|
5208
|
-
};
|
|
5209
|
-
continue;
|
|
5210
4974
|
}
|
|
5211
|
-
throw unsupportedDefaultInputError(key, collector);
|
|
5212
4975
|
}
|
|
5213
|
-
return
|
|
4976
|
+
return [...zoneIds];
|
|
5214
4977
|
}
|
|
5215
|
-
function
|
|
4978
|
+
function findCardInputKey(interaction) {
|
|
4979
|
+
return Object.entries(interactionInputsOf(interaction)).find(
|
|
4980
|
+
([, collector]) => collector.kind === "card"
|
|
4981
|
+
)?.[0];
|
|
4982
|
+
}
|
|
4983
|
+
function findCardInputKeyForZone(interaction, zoneId) {
|
|
4984
|
+
return Object.entries(interactionInputsOf(interaction)).find(
|
|
4985
|
+
([, collector]) => collector.kind === "card" && (collector.meta.zoneIds ?? [collector.meta.zoneId]).map(String).includes(zoneId)
|
|
4986
|
+
)?.[0];
|
|
4987
|
+
}
|
|
4988
|
+
|
|
4989
|
+
// src/reducer/bundle/trusted/collector-eligibility.ts
|
|
4990
|
+
function collectEligibleTargets(interaction, domainState, playerId, options = {}) {
|
|
5216
4991
|
const collectors = interactionInputsOf(interaction);
|
|
5217
|
-
const
|
|
5218
|
-
Object.values(collectors).flatMap((collector) => [
|
|
5219
|
-
...collector.dependsOn ?? []
|
|
5220
|
-
])
|
|
5221
|
-
);
|
|
5222
|
-
const collectedEligibleTargets = options.includeEligibleTargets === false && dependencyKeys.size === 0 ? {} : collectEligibleTargets(interaction, domainState, playerId, options);
|
|
5223
|
-
const eligibleTargets = options.includeEligibleTargets === false ? Object.fromEntries(
|
|
5224
|
-
Object.entries(collectedEligibleTargets).filter(
|
|
5225
|
-
([key]) => dependencyKeys.has(key)
|
|
5226
|
-
)
|
|
5227
|
-
) : collectedEligibleTargets;
|
|
5228
|
-
const domainsByKey = collectInputDomains(
|
|
5229
|
-
interaction,
|
|
5230
|
-
domainState,
|
|
5231
|
-
playerId,
|
|
5232
|
-
eligibleTargets,
|
|
5233
|
-
options
|
|
5234
|
-
);
|
|
4992
|
+
const result = {};
|
|
5235
4993
|
let queriesLazy = options.queries ?? null;
|
|
5236
4994
|
const queries = () => queriesLazy ??= createStateQueries(
|
|
5237
4995
|
domainState
|
|
5238
4996
|
);
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
if (!domain && collector.kind === "prompt") {
|
|
5247
|
-
return [];
|
|
5248
|
-
}
|
|
5249
|
-
if (!domain) {
|
|
5250
|
-
throw unsupportedDefaultInputError(key, collector);
|
|
5251
|
-
}
|
|
5252
|
-
const dynamicDefault = collector.resolveDefaultValue?.(
|
|
5253
|
-
domainState,
|
|
5254
|
-
playerId,
|
|
5255
|
-
queries(),
|
|
5256
|
-
derived(),
|
|
5257
|
-
domain
|
|
5258
|
-
);
|
|
5259
|
-
const defaultValue = "defaultValue" in collector ? collector.defaultValue : dynamicDefault;
|
|
5260
|
-
warnConcreteDependentChoiceDefault({
|
|
5261
|
-
inputKey: key,
|
|
5262
|
-
collector,
|
|
5263
|
-
domain,
|
|
5264
|
-
defaultValue,
|
|
5265
|
-
dependencyKeys
|
|
5266
|
-
});
|
|
5267
|
-
return [
|
|
5268
|
-
{
|
|
5269
|
-
key,
|
|
5270
|
-
kind: collector.kind,
|
|
5271
|
-
domain,
|
|
5272
|
-
...defaultValue !== void 0 ? { defaultValue } : {}
|
|
5273
|
-
}
|
|
5274
|
-
];
|
|
5275
|
-
});
|
|
5276
|
-
}
|
|
5277
|
-
var concreteDependentChoiceDefaultWarnings = /* @__PURE__ */ new Set();
|
|
5278
|
-
function shouldEmitAuthoringWarning() {
|
|
5279
|
-
const env = globalThis.process?.env;
|
|
5280
|
-
return env?.NODE_ENV !== "production" && env?.DREAMBOARD_SUPPRESS_AUTHORING_WARNINGS !== "1";
|
|
5281
|
-
}
|
|
5282
|
-
function warnConcreteDependentChoiceDefault({
|
|
5283
|
-
inputKey,
|
|
5284
|
-
collector,
|
|
5285
|
-
domain,
|
|
5286
|
-
defaultValue,
|
|
5287
|
-
dependencyKeys
|
|
5288
|
-
}) {
|
|
5289
|
-
if (!shouldEmitAuthoringWarning() || !dependencyKeys.has(inputKey) || collector.kind !== "form" || domain.type !== "choice" || defaultValue === void 0 || defaultValue === null) {
|
|
5290
|
-
return;
|
|
5291
|
-
}
|
|
5292
|
-
const warningKey = `${inputKey}:${String(defaultValue)}`;
|
|
5293
|
-
if (concreteDependentChoiceDefaultWarnings.has(warningKey)) {
|
|
5294
|
-
return;
|
|
5295
|
-
}
|
|
5296
|
-
concreteDependentChoiceDefaultWarnings.add(warningKey);
|
|
5297
|
-
console.warn(
|
|
5298
|
-
`[dreamboard] Form choice input "${inputKey}" feeds another collector and defaulted to "${String(
|
|
5299
|
-
defaultValue
|
|
5300
|
-
)}". Dependent choices that select the object an action applies to should usually use defaultValue: () => undefined so collection stays explicit.`
|
|
5301
|
-
);
|
|
5302
|
-
}
|
|
5303
|
-
function collectFirstCardZoneId(interaction) {
|
|
5304
|
-
const collectors = interactionInputsOf(interaction);
|
|
5305
|
-
for (const collector of Object.values(collectors)) {
|
|
5306
|
-
if (collector.kind === "card") {
|
|
5307
|
-
if (collector.meta.zoneId.length > 0) {
|
|
5308
|
-
return collector.meta.zoneId;
|
|
5309
|
-
}
|
|
4997
|
+
for (const [key, collector] of Object.entries(collectors)) {
|
|
4998
|
+
if (!collector.eligibleTargets) continue;
|
|
4999
|
+
const cacheKey = options.eligibleTargetCachePrefix ? `${options.eligibleTargetCachePrefix}:${key}` : null;
|
|
5000
|
+
const cached = cacheKey ? options.eligibleTargetCache?.get(cacheKey) : void 0;
|
|
5001
|
+
if (cached) {
|
|
5002
|
+
result[key] = cached;
|
|
5003
|
+
continue;
|
|
5310
5004
|
}
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5005
|
+
const targets = collector.eligibleTargets(
|
|
5006
|
+
domainState,
|
|
5007
|
+
playerId,
|
|
5008
|
+
queries()
|
|
5009
|
+
);
|
|
5010
|
+
const resolved = Array.from(targets).map(
|
|
5011
|
+
(t) => String(t)
|
|
5012
|
+
);
|
|
5013
|
+
result[key] = resolved;
|
|
5014
|
+
if (cacheKey) {
|
|
5015
|
+
options.eligibleTargetCache?.set(cacheKey, resolved);
|
|
5322
5016
|
}
|
|
5323
5017
|
}
|
|
5324
|
-
return
|
|
5018
|
+
return result;
|
|
5325
5019
|
}
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5020
|
+
|
|
5021
|
+
// src/reducer/parse-utils.ts
|
|
5022
|
+
function formatIssue(label, issue) {
|
|
5023
|
+
const path = issue.path.map(
|
|
5024
|
+
(segment) => typeof segment === "symbol" ? segment.toString() : String(segment)
|
|
5025
|
+
).join(".");
|
|
5026
|
+
return `${path || label}: ${issue.message}`;
|
|
5027
|
+
}
|
|
5028
|
+
function safeParseOrThrow(schema, value, label) {
|
|
5029
|
+
const parsed = schema.safeParse(value);
|
|
5030
|
+
if (!parsed.success) {
|
|
5031
|
+
const message = parsed.error.issues.map((issue) => formatIssue(label, issue)).join("; ");
|
|
5032
|
+
throw new Error(message || `Invalid ${label}`);
|
|
5335
5033
|
}
|
|
5336
|
-
return
|
|
5034
|
+
return parsed.data;
|
|
5035
|
+
}
|
|
5036
|
+
|
|
5037
|
+
// src/reducer/bundle/trusted/interaction-types.ts
|
|
5038
|
+
function makeValidationError(errorCode, message) {
|
|
5039
|
+
return {
|
|
5040
|
+
valid: false,
|
|
5041
|
+
errorCode,
|
|
5042
|
+
message
|
|
5043
|
+
};
|
|
5337
5044
|
}
|
|
5045
|
+
|
|
5046
|
+
// src/reducer/bundle/trusted/collector-params.ts
|
|
5338
5047
|
function parseInteractionParams(interaction, rawParams, options = {}) {
|
|
5339
5048
|
const collectors = interactionInputsOf(interaction);
|
|
5340
5049
|
const record = rawParams ?? {};
|
|
@@ -5490,16 +5199,6 @@ function stableValueKey(value) {
|
|
|
5490
5199
|
return `json:${JSON.stringify(value)}`;
|
|
5491
5200
|
}
|
|
5492
5201
|
}
|
|
5493
|
-
function findCardInputKey(interaction) {
|
|
5494
|
-
return Object.entries(interactionInputsOf(interaction)).find(
|
|
5495
|
-
([, collector]) => collector.kind === "card"
|
|
5496
|
-
)?.[0];
|
|
5497
|
-
}
|
|
5498
|
-
function findCardInputKeyForZone(interaction, zoneId) {
|
|
5499
|
-
return Object.entries(interactionInputsOf(interaction)).find(
|
|
5500
|
-
([, collector]) => collector.kind === "card" && (collector.meta.zoneIds ?? [collector.meta.zoneId]).map(String).includes(zoneId)
|
|
5501
|
-
)?.[0];
|
|
5502
|
-
}
|
|
5503
5202
|
|
|
5504
5203
|
// src/reducer/bundle/trusted/interaction-authorization.ts
|
|
5505
5204
|
function resolvePromptToSet(to) {
|
|
@@ -5548,55 +5247,373 @@ function createInteractionAuthorization(scope) {
|
|
|
5548
5247
|
)
|
|
5549
5248
|
};
|
|
5550
5249
|
}
|
|
5551
|
-
if (phase.actor) {
|
|
5552
|
-
const resolved = phase.actor({
|
|
5553
|
-
...scope.buildRuntimeArgs(
|
|
5554
|
-
state,
|
|
5555
|
-
{
|
|
5556
|
-
state: projection?.domainState ?? scope.toDomainState(state)
|
|
5557
|
-
},
|
|
5558
|
-
projection
|
|
5250
|
+
if (phase.actor) {
|
|
5251
|
+
const resolved = phase.actor({
|
|
5252
|
+
...scope.buildRuntimeArgs(
|
|
5253
|
+
state,
|
|
5254
|
+
{
|
|
5255
|
+
state: projection?.domainState ?? scope.toDomainState(state)
|
|
5256
|
+
},
|
|
5257
|
+
projection
|
|
5258
|
+
)
|
|
5259
|
+
});
|
|
5260
|
+
return {
|
|
5261
|
+
mode: "actors",
|
|
5262
|
+
actors: resolvePromptToSet(resolved)
|
|
5263
|
+
};
|
|
5264
|
+
}
|
|
5265
|
+
return { mode: "active" };
|
|
5266
|
+
}
|
|
5267
|
+
function isActorAuthorized(state, playerId, authorization) {
|
|
5268
|
+
if (authorization.mode === "addressees") {
|
|
5269
|
+
return authorization.addressees.has(playerId);
|
|
5270
|
+
}
|
|
5271
|
+
if (authorization.mode === "actors") {
|
|
5272
|
+
return authorization.actors.has(playerId);
|
|
5273
|
+
}
|
|
5274
|
+
const active = state.flow.activePlayers;
|
|
5275
|
+
if (active.length === 0) {
|
|
5276
|
+
return true;
|
|
5277
|
+
}
|
|
5278
|
+
return active.includes(playerId);
|
|
5279
|
+
}
|
|
5280
|
+
function isInteractionVisible(interaction, authorization, authorized) {
|
|
5281
|
+
return !(authorization.mode === "addressees" && !authorized) && !(interaction.visibility === "actorsOnly" && !authorized);
|
|
5282
|
+
}
|
|
5283
|
+
return {
|
|
5284
|
+
isActorAuthorized,
|
|
5285
|
+
isInteractionVisible,
|
|
5286
|
+
resolveInteractionActorAuthorization
|
|
5287
|
+
};
|
|
5288
|
+
}
|
|
5289
|
+
|
|
5290
|
+
// src/reducer/bundle/trusted/collector-domains.ts
|
|
5291
|
+
var MAX_EAGER_DEPENDENT_DOMAIN_CASES = 64;
|
|
5292
|
+
function withSelection(domain, collector) {
|
|
5293
|
+
if (!collector.selection) return domain;
|
|
5294
|
+
return { ...domain, selection: collector.selection };
|
|
5295
|
+
}
|
|
5296
|
+
function lazyTargetDomainFromCollectorMetadata(key, collector, dependencies) {
|
|
5297
|
+
const metadata = collectTargetDomainMetadata(collector);
|
|
5298
|
+
if (collector.kind === "card") {
|
|
5299
|
+
return withSelection(
|
|
5300
|
+
{
|
|
5301
|
+
type: "cardTarget",
|
|
5302
|
+
projection: "lazy",
|
|
5303
|
+
targetKind: "card",
|
|
5304
|
+
zoneIds: metadata.zoneIds ?? (metadata.zoneId === void 0 ? [] : [metadata.zoneId]),
|
|
5305
|
+
dependencies: {
|
|
5306
|
+
mode: "lazy",
|
|
5307
|
+
dependsOn: dependencies,
|
|
5308
|
+
resolver: { inputKey: key }
|
|
5309
|
+
}
|
|
5310
|
+
},
|
|
5311
|
+
collector
|
|
5312
|
+
);
|
|
5313
|
+
}
|
|
5314
|
+
if (collector.kind === "board-edge" || collector.kind === "board-space" || collector.kind === "board-tile" || collector.kind === "board-vertex") {
|
|
5315
|
+
return withSelection(
|
|
5316
|
+
{
|
|
5317
|
+
type: "boardTarget",
|
|
5318
|
+
projection: "lazy",
|
|
5319
|
+
targetKind: metadata.targetKind ?? collector.kind.replace("board-", ""),
|
|
5320
|
+
boardId: metadata.boardId ?? "",
|
|
5321
|
+
...metadata.valueKind ? { valueKind: metadata.valueKind } : {},
|
|
5322
|
+
dependencies: {
|
|
5323
|
+
mode: "lazy",
|
|
5324
|
+
dependsOn: dependencies,
|
|
5325
|
+
resolver: { inputKey: key }
|
|
5326
|
+
}
|
|
5327
|
+
},
|
|
5328
|
+
collector
|
|
5329
|
+
);
|
|
5330
|
+
}
|
|
5331
|
+
return null;
|
|
5332
|
+
}
|
|
5333
|
+
function finiteValuesForDependency(key, domain) {
|
|
5334
|
+
if (!domain) {
|
|
5335
|
+
throw new Error(
|
|
5336
|
+
`Interaction input '${key}' is declared as a dependency before it has a projected domain.`
|
|
5337
|
+
);
|
|
5338
|
+
}
|
|
5339
|
+
if (domain.type === "cardTarget" || domain.type === "boardTarget") {
|
|
5340
|
+
if (domain.projection !== "resolved") {
|
|
5341
|
+
throw new Error(
|
|
5342
|
+
`Interaction input '${key}' cannot be used as a dependency because its target domain is not finite.`
|
|
5343
|
+
);
|
|
5344
|
+
}
|
|
5345
|
+
return [...domain.eligibleTargets];
|
|
5346
|
+
}
|
|
5347
|
+
if (domain.type === "choice") {
|
|
5348
|
+
return domain.choices.flatMap(
|
|
5349
|
+
(choice) => choice.value === null ? [] : [choice.value]
|
|
5350
|
+
);
|
|
5351
|
+
}
|
|
5352
|
+
throw new Error(
|
|
5353
|
+
`Interaction input '${key}' cannot be used as a dependency. V1 supports finite target and choice dependencies only.`
|
|
5354
|
+
);
|
|
5355
|
+
}
|
|
5356
|
+
function cartesianDependencyTuples(dependencies, domainsByKey) {
|
|
5357
|
+
return dependencies.reduce(
|
|
5358
|
+
(tuples, key) => {
|
|
5359
|
+
const values = finiteValuesForDependency(key, domainsByKey[key]);
|
|
5360
|
+
return tuples.flatMap(
|
|
5361
|
+
(tuple) => values.map((value) => ({ ...tuple, [key]: value }))
|
|
5362
|
+
);
|
|
5363
|
+
},
|
|
5364
|
+
[{}]
|
|
5365
|
+
);
|
|
5366
|
+
}
|
|
5367
|
+
function withoutDependentProjection(domain) {
|
|
5368
|
+
const { dependencies: _dependencies, ...rest } = domain;
|
|
5369
|
+
return rest;
|
|
5370
|
+
}
|
|
5371
|
+
function toLazyTargetDomain(key, domain, dependencies) {
|
|
5372
|
+
if (domain.type === "cardTarget") {
|
|
5373
|
+
return {
|
|
5374
|
+
type: "cardTarget",
|
|
5375
|
+
projection: "lazy",
|
|
5376
|
+
targetKind: "card",
|
|
5377
|
+
zoneIds: domain.zoneIds,
|
|
5378
|
+
...domain.selection ? { selection: domain.selection } : {},
|
|
5379
|
+
dependencies: {
|
|
5380
|
+
mode: "lazy",
|
|
5381
|
+
dependsOn: dependencies,
|
|
5382
|
+
resolver: { inputKey: key }
|
|
5383
|
+
}
|
|
5384
|
+
};
|
|
5385
|
+
}
|
|
5386
|
+
if (domain.type === "boardTarget") {
|
|
5387
|
+
return {
|
|
5388
|
+
type: "boardTarget",
|
|
5389
|
+
projection: "lazy",
|
|
5390
|
+
targetKind: domain.targetKind,
|
|
5391
|
+
boardId: domain.boardId,
|
|
5392
|
+
...domain.valueKind ? { valueKind: domain.valueKind } : {},
|
|
5393
|
+
...domain.selection ? { selection: domain.selection } : {},
|
|
5394
|
+
dependencies: {
|
|
5395
|
+
mode: "lazy",
|
|
5396
|
+
dependsOn: dependencies,
|
|
5397
|
+
resolver: { inputKey: key }
|
|
5398
|
+
}
|
|
5399
|
+
};
|
|
5400
|
+
}
|
|
5401
|
+
return null;
|
|
5402
|
+
}
|
|
5403
|
+
function dependencyCaseCount(dependencies, domainsByKey) {
|
|
5404
|
+
return dependencies.map((key) => finiteValuesForDependency(key, domainsByKey[key]).length).reduce((total, count) => total * count, 1);
|
|
5405
|
+
}
|
|
5406
|
+
function unsupportedDefaultInputError(key, collector) {
|
|
5407
|
+
return new Error(
|
|
5408
|
+
`Interaction input '${key}' uses a '${collector.kind}' collector without a default-renderable domain or target metadata. Use formInput.choice(...), formInput.choiceList(...), formInput.number(...), formInput.resourceMap(...), cardInput(...), or boardInput(...). For custom payloads, use a custom interaction surface with paramsSchema instead of the default InteractionForm.`
|
|
5409
|
+
);
|
|
5410
|
+
}
|
|
5411
|
+
function collectInputDomains(interaction, domainState, playerId, eligibleTargets, options = {}) {
|
|
5412
|
+
const collectors = interactionInputsOf(interaction);
|
|
5413
|
+
let queriesLazy = options.queries ?? null;
|
|
5414
|
+
const queries = () => queriesLazy ??= createStateQueries(
|
|
5415
|
+
domainState
|
|
5416
|
+
);
|
|
5417
|
+
let derivedLazy = options.derived ?? null;
|
|
5418
|
+
const derived = () => derivedLazy ??= createDerivedResolver(domainState, { q: queries() });
|
|
5419
|
+
const result = {};
|
|
5420
|
+
for (const [key, collector] of Object.entries(collectors)) {
|
|
5421
|
+
if (collector.kind === "rng") {
|
|
5422
|
+
continue;
|
|
5423
|
+
}
|
|
5424
|
+
if (collector.kind === "prompt") {
|
|
5425
|
+
const optionFactory = collector.meta?.options;
|
|
5426
|
+
if (!optionFactory) continue;
|
|
5427
|
+
result[key] = {
|
|
5428
|
+
type: "choice",
|
|
5429
|
+
choices: optionFactory(domainState, playerId, queries()).map(
|
|
5430
|
+
(option) => ({
|
|
5431
|
+
value: String(option.id),
|
|
5432
|
+
label: option.label ?? String(option.id),
|
|
5433
|
+
...(() => {
|
|
5434
|
+
const issue = collector.validateTarget?.(
|
|
5435
|
+
domainState,
|
|
5436
|
+
playerId,
|
|
5437
|
+
queries(),
|
|
5438
|
+
String(option.id)
|
|
5439
|
+
);
|
|
5440
|
+
return issue ? {
|
|
5441
|
+
disabled: true,
|
|
5442
|
+
disabledReason: issue.message ?? issue.errorCode
|
|
5443
|
+
} : {};
|
|
5444
|
+
})()
|
|
5445
|
+
})
|
|
5446
|
+
)
|
|
5447
|
+
};
|
|
5448
|
+
continue;
|
|
5449
|
+
}
|
|
5450
|
+
if (collector.domain) {
|
|
5451
|
+
const domainProjector = collector.domain;
|
|
5452
|
+
const dependencies = collector.dependsOn ?? [];
|
|
5453
|
+
if (options.includeEligibleTargets === false && !Object.prototype.hasOwnProperty.call(eligibleTargets, key)) {
|
|
5454
|
+
const lazyDomain2 = lazyTargetDomainFromCollectorMetadata(
|
|
5455
|
+
key,
|
|
5456
|
+
collector,
|
|
5457
|
+
dependencies
|
|
5458
|
+
);
|
|
5459
|
+
if (lazyDomain2) {
|
|
5460
|
+
result[key] = lazyDomain2;
|
|
5461
|
+
continue;
|
|
5462
|
+
}
|
|
5463
|
+
}
|
|
5464
|
+
const baseDomain = withSelection(
|
|
5465
|
+
domainProjector(
|
|
5466
|
+
domainState,
|
|
5467
|
+
playerId,
|
|
5468
|
+
queries(),
|
|
5469
|
+
derived(),
|
|
5470
|
+
{}
|
|
5471
|
+
),
|
|
5472
|
+
collector
|
|
5473
|
+
);
|
|
5474
|
+
if (dependencies.length === 0) {
|
|
5475
|
+
result[key] = baseDomain;
|
|
5476
|
+
continue;
|
|
5477
|
+
}
|
|
5478
|
+
const caseCount = dependencyCaseCount(dependencies, result);
|
|
5479
|
+
const lazyDomain = caseCount > MAX_EAGER_DEPENDENT_DOMAIN_CASES ? toLazyTargetDomain(key, baseDomain, dependencies) : null;
|
|
5480
|
+
if (lazyDomain) {
|
|
5481
|
+
result[key] = lazyDomain;
|
|
5482
|
+
continue;
|
|
5483
|
+
}
|
|
5484
|
+
const dependentCases = cartesianDependencyTuples(
|
|
5485
|
+
dependencies,
|
|
5486
|
+
result
|
|
5487
|
+
).map((values) => ({
|
|
5488
|
+
when: values,
|
|
5489
|
+
domain: withoutDependentProjection(
|
|
5490
|
+
withSelection(
|
|
5491
|
+
domainProjector(
|
|
5492
|
+
domainState,
|
|
5493
|
+
playerId,
|
|
5494
|
+
queries(),
|
|
5495
|
+
derived(),
|
|
5496
|
+
values
|
|
5497
|
+
),
|
|
5498
|
+
collector
|
|
5499
|
+
)
|
|
5559
5500
|
)
|
|
5560
|
-
});
|
|
5561
|
-
|
|
5562
|
-
|
|
5563
|
-
|
|
5501
|
+
}));
|
|
5502
|
+
result[key] = {
|
|
5503
|
+
...baseDomain,
|
|
5504
|
+
dependencies: {
|
|
5505
|
+
mode: "eager",
|
|
5506
|
+
dependentCases
|
|
5507
|
+
}
|
|
5564
5508
|
};
|
|
5509
|
+
continue;
|
|
5565
5510
|
}
|
|
5566
|
-
|
|
5511
|
+
throw unsupportedDefaultInputError(key, collector);
|
|
5567
5512
|
}
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5513
|
+
return result;
|
|
5514
|
+
}
|
|
5515
|
+
function collectInteractionInputs(interaction, domainState, playerId, options = {}) {
|
|
5516
|
+
const collectors = interactionInputsOf(interaction);
|
|
5517
|
+
const dependencyKeys = new Set(
|
|
5518
|
+
Object.values(collectors).flatMap((collector) => [
|
|
5519
|
+
...collector.dependsOn ?? []
|
|
5520
|
+
])
|
|
5521
|
+
);
|
|
5522
|
+
const collectedEligibleTargets = options.includeEligibleTargets === false && dependencyKeys.size === 0 ? {} : collectEligibleTargets(interaction, domainState, playerId, options);
|
|
5523
|
+
const eligibleTargets = options.includeEligibleTargets === false ? Object.fromEntries(
|
|
5524
|
+
Object.entries(collectedEligibleTargets).filter(
|
|
5525
|
+
([key]) => dependencyKeys.has(key)
|
|
5526
|
+
)
|
|
5527
|
+
) : collectedEligibleTargets;
|
|
5528
|
+
const domainsByKey = collectInputDomains(
|
|
5529
|
+
interaction,
|
|
5530
|
+
domainState,
|
|
5531
|
+
playerId,
|
|
5532
|
+
eligibleTargets,
|
|
5533
|
+
options
|
|
5534
|
+
);
|
|
5535
|
+
let queriesLazy = options.queries ?? null;
|
|
5536
|
+
const queries = () => queriesLazy ??= createStateQueries(
|
|
5537
|
+
domainState
|
|
5538
|
+
);
|
|
5539
|
+
let derivedLazy = options.derived ?? null;
|
|
5540
|
+
const derived = () => derivedLazy ??= createDerivedResolver(domainState, { q: queries() });
|
|
5541
|
+
return Object.entries(collectors).flatMap(([key, collector]) => {
|
|
5542
|
+
if (collector.kind === "rng") {
|
|
5543
|
+
return [];
|
|
5571
5544
|
}
|
|
5572
|
-
|
|
5573
|
-
|
|
5545
|
+
const domain = domainsByKey[key];
|
|
5546
|
+
if (!domain && collector.kind === "prompt") {
|
|
5547
|
+
return [];
|
|
5574
5548
|
}
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
return true;
|
|
5549
|
+
if (!domain) {
|
|
5550
|
+
throw unsupportedDefaultInputError(key, collector);
|
|
5578
5551
|
}
|
|
5579
|
-
|
|
5552
|
+
const dynamicDefault = collector.resolveDefaultValue?.(
|
|
5553
|
+
domainState,
|
|
5554
|
+
playerId,
|
|
5555
|
+
queries(),
|
|
5556
|
+
derived(),
|
|
5557
|
+
domain
|
|
5558
|
+
);
|
|
5559
|
+
const defaultValue = "defaultValue" in collector ? collector.defaultValue : dynamicDefault;
|
|
5560
|
+
warnConcreteDependentChoiceDefault({
|
|
5561
|
+
inputKey: key,
|
|
5562
|
+
collector,
|
|
5563
|
+
domain,
|
|
5564
|
+
defaultValue,
|
|
5565
|
+
dependencyKeys
|
|
5566
|
+
});
|
|
5567
|
+
return [
|
|
5568
|
+
{
|
|
5569
|
+
key,
|
|
5570
|
+
kind: collector.kind,
|
|
5571
|
+
domain,
|
|
5572
|
+
...defaultValue !== void 0 ? { defaultValue } : {}
|
|
5573
|
+
}
|
|
5574
|
+
];
|
|
5575
|
+
});
|
|
5576
|
+
}
|
|
5577
|
+
var concreteDependentChoiceDefaultWarnings = /* @__PURE__ */ new Set();
|
|
5578
|
+
var AUTHORING_WARNINGS_FLAG = "__DREAMBOARD_AUTHORING_WARNINGS__";
|
|
5579
|
+
function shouldEmitAuthoringWarning() {
|
|
5580
|
+
return globalThis[AUTHORING_WARNINGS_FLAG] === true;
|
|
5581
|
+
}
|
|
5582
|
+
function warnConcreteDependentChoiceDefault({
|
|
5583
|
+
inputKey,
|
|
5584
|
+
collector,
|
|
5585
|
+
domain,
|
|
5586
|
+
defaultValue,
|
|
5587
|
+
dependencyKeys
|
|
5588
|
+
}) {
|
|
5589
|
+
if (!shouldEmitAuthoringWarning() || !dependencyKeys.has(inputKey) || collector.kind !== "form" || domain.type !== "choice" || defaultValue === void 0 || defaultValue === null) {
|
|
5590
|
+
return;
|
|
5580
5591
|
}
|
|
5581
|
-
|
|
5582
|
-
|
|
5592
|
+
const warningKey = `${inputKey}:${String(defaultValue)}`;
|
|
5593
|
+
if (concreteDependentChoiceDefaultWarnings.has(warningKey)) {
|
|
5594
|
+
return;
|
|
5583
5595
|
}
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
// src/reducer/bundle/trusted/interaction-decision.ts
|
|
5592
|
-
function issueFromRule(rule) {
|
|
5593
|
-
return { errorCode: rule.errorCode, message: rule.message };
|
|
5596
|
+
concreteDependentChoiceDefaultWarnings.add(warningKey);
|
|
5597
|
+
console.warn(
|
|
5598
|
+
`[dreamboard] Form choice input "${inputKey}" feeds another collector and defaulted to "${String(
|
|
5599
|
+
defaultValue
|
|
5600
|
+
)}". Dependent choices that select the object an action applies to should usually use defaultValue: () => undefined so collection stays explicit.`
|
|
5601
|
+
);
|
|
5594
5602
|
}
|
|
5595
|
-
function
|
|
5596
|
-
|
|
5597
|
-
|
|
5603
|
+
function collectPromptOptions(interaction, domainState, playerId, queries) {
|
|
5604
|
+
for (const collector of Object.values(interaction.inputs)) {
|
|
5605
|
+
if (collector.kind !== "prompt") continue;
|
|
5606
|
+
const factory = collector.meta?.options;
|
|
5607
|
+
if (!factory) continue;
|
|
5608
|
+
return factory(domainState, playerId, queries).map((option) => ({
|
|
5609
|
+
id: String(option.id),
|
|
5610
|
+
...option.label !== void 0 ? { label: option.label } : {}
|
|
5611
|
+
}));
|
|
5612
|
+
}
|
|
5598
5613
|
return void 0;
|
|
5599
5614
|
}
|
|
5615
|
+
|
|
5616
|
+
// src/reducer/bundle/trusted/interaction-descriptor.ts
|
|
5600
5617
|
function humanizeInteractionId(id) {
|
|
5601
5618
|
if (!id) return id;
|
|
5602
5619
|
const withSpaces = id.replace(/[-_]+/g, " ").replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").trim();
|
|
@@ -5738,6 +5755,78 @@ function interactionAvailabilityFromDecision(decision) {
|
|
|
5738
5755
|
reason: decision.unavailableReason ?? "Interaction unavailable"
|
|
5739
5756
|
};
|
|
5740
5757
|
}
|
|
5758
|
+
function buildInteractionDescriptor(scope, state, playerId, interactionId, interaction, decision, options = {}) {
|
|
5759
|
+
const domainState = options.projection?.domainState ?? scope.toDomainState(state);
|
|
5760
|
+
const phaseName = state.flow.currentPhase;
|
|
5761
|
+
const interactionInputs = interactionInputsOf(interaction);
|
|
5762
|
+
const metadata = projectInteractionMetadata({
|
|
5763
|
+
...interaction,
|
|
5764
|
+
inputs: interactionInputs
|
|
5765
|
+
});
|
|
5766
|
+
const queries = options.projection?.q ?? createStateQueries(domainState);
|
|
5767
|
+
const derived = options.projection?.derived;
|
|
5768
|
+
const shouldMaterializeInputDomains = decision.available || decision.unavailableReason !== "Not your turn";
|
|
5769
|
+
const promptContext = metadata.kind === "prompt" ? {
|
|
5770
|
+
to: playerId,
|
|
5771
|
+
title: humanizeInteractionId(interactionId),
|
|
5772
|
+
options: shouldMaterializeInputDomains ? collectPromptOptions(
|
|
5773
|
+
{ inputs: interactionInputs },
|
|
5774
|
+
domainState,
|
|
5775
|
+
playerId,
|
|
5776
|
+
queries
|
|
5777
|
+
) : void 0
|
|
5778
|
+
} : void 0;
|
|
5779
|
+
const inputs = shouldMaterializeInputDomains ? enrichResourceInputPresentation(
|
|
5780
|
+
collectInteractionInputs(interaction, domainState, playerId, {
|
|
5781
|
+
queries,
|
|
5782
|
+
derived,
|
|
5783
|
+
eligibleTargetCache: options.projection?.eligibleTargets,
|
|
5784
|
+
eligibleTargetCachePrefix: `${phaseName}:${String(
|
|
5785
|
+
interactionId
|
|
5786
|
+
)}:${String(playerId)}`,
|
|
5787
|
+
includeEligibleTargets: options.includeEligibleTargets
|
|
5788
|
+
}),
|
|
5789
|
+
scope.definition.contract.manifest
|
|
5790
|
+
) : [];
|
|
5791
|
+
const baseDescriptor = {
|
|
5792
|
+
phaseName,
|
|
5793
|
+
interactionKey: `${phaseName}.${interactionId}`,
|
|
5794
|
+
interactionId,
|
|
5795
|
+
commit: metadata.commit,
|
|
5796
|
+
zoneId: collectFirstCardZoneId(interaction),
|
|
5797
|
+
zoneIds: collectCardZoneIds(interaction),
|
|
5798
|
+
inputs,
|
|
5799
|
+
cost: decision.cost ? { ...decision.cost } : void 0,
|
|
5800
|
+
currentResources: decision.cost ? {
|
|
5801
|
+
...queries.player.resources(playerId)
|
|
5802
|
+
} : void 0,
|
|
5803
|
+
availability: interactionAvailabilityFromDecision(decision)
|
|
5804
|
+
};
|
|
5805
|
+
if (metadata.kind === "prompt") {
|
|
5806
|
+
return {
|
|
5807
|
+
...baseDescriptor,
|
|
5808
|
+
kind: "prompt",
|
|
5809
|
+
context: promptContext ?? {
|
|
5810
|
+
to: playerId,
|
|
5811
|
+
title: humanizeInteractionId(interactionId)
|
|
5812
|
+
}
|
|
5813
|
+
};
|
|
5814
|
+
}
|
|
5815
|
+
return {
|
|
5816
|
+
...baseDescriptor,
|
|
5817
|
+
kind: "action"
|
|
5818
|
+
};
|
|
5819
|
+
}
|
|
5820
|
+
|
|
5821
|
+
// src/reducer/bundle/trusted/interaction-decision.ts
|
|
5822
|
+
function issueFromRule(rule) {
|
|
5823
|
+
return { errorCode: rule.errorCode, message: rule.message };
|
|
5824
|
+
}
|
|
5825
|
+
function issueFromRuleValidationResult(rule, result) {
|
|
5826
|
+
if (result === false) return issueFromRule(rule);
|
|
5827
|
+
if (result && typeof result === "object") return result;
|
|
5828
|
+
return void 0;
|
|
5829
|
+
}
|
|
5741
5830
|
function createInteractionDecisionResolver(scope, stages, authorization) {
|
|
5742
5831
|
function evaluateInteractionCost(state, interaction, playerId, params, projection) {
|
|
5743
5832
|
if (!interaction.cost) {
|
|
@@ -5760,68 +5849,6 @@ function createInteractionDecisionResolver(scope, stages, authorization) {
|
|
|
5760
5849
|
return { error };
|
|
5761
5850
|
}
|
|
5762
5851
|
}
|
|
5763
|
-
function buildBaseDescriptor(state, playerId, interactionId, interaction, decision, options = {}) {
|
|
5764
|
-
const domainState = options.projection?.domainState ?? scope.toDomainState(state);
|
|
5765
|
-
const phaseName = state.flow.currentPhase;
|
|
5766
|
-
const interactionInputs = interactionInputsOf(interaction);
|
|
5767
|
-
const metadata = projectInteractionMetadata({
|
|
5768
|
-
...interaction,
|
|
5769
|
-
inputs: interactionInputs
|
|
5770
|
-
});
|
|
5771
|
-
const queries = options.projection?.q ?? createStateQueries(domainState);
|
|
5772
|
-
const derived = options.projection?.derived;
|
|
5773
|
-
const shouldMaterializeInputDomains = decision.available || decision.unavailableReason !== "Not your turn";
|
|
5774
|
-
const promptContext = metadata.kind === "prompt" ? {
|
|
5775
|
-
to: playerId,
|
|
5776
|
-
title: humanizeInteractionId(interactionId),
|
|
5777
|
-
options: shouldMaterializeInputDomains ? collectPromptOptions(
|
|
5778
|
-
{ inputs: interactionInputs },
|
|
5779
|
-
domainState,
|
|
5780
|
-
playerId,
|
|
5781
|
-
queries
|
|
5782
|
-
) : void 0
|
|
5783
|
-
} : void 0;
|
|
5784
|
-
const inputs = shouldMaterializeInputDomains ? enrichResourceInputPresentation(
|
|
5785
|
-
collectInteractionInputs(interaction, domainState, playerId, {
|
|
5786
|
-
queries,
|
|
5787
|
-
derived,
|
|
5788
|
-
eligibleTargetCache: options.projection?.eligibleTargets,
|
|
5789
|
-
eligibleTargetCachePrefix: `${phaseName}:${String(
|
|
5790
|
-
interactionId
|
|
5791
|
-
)}:${String(playerId)}`,
|
|
5792
|
-
includeEligibleTargets: options.includeEligibleTargets
|
|
5793
|
-
}),
|
|
5794
|
-
scope.definition.contract.manifest
|
|
5795
|
-
) : [];
|
|
5796
|
-
const baseDescriptor = {
|
|
5797
|
-
phaseName,
|
|
5798
|
-
interactionKey: `${phaseName}.${interactionId}`,
|
|
5799
|
-
interactionId,
|
|
5800
|
-
commit: metadata.commit,
|
|
5801
|
-
zoneId: collectFirstCardZoneId(interaction),
|
|
5802
|
-
zoneIds: collectCardZoneIds(interaction),
|
|
5803
|
-
inputs,
|
|
5804
|
-
cost: decision.cost ? { ...decision.cost } : void 0,
|
|
5805
|
-
currentResources: decision.cost ? {
|
|
5806
|
-
...queries.player.resources(playerId)
|
|
5807
|
-
} : void 0,
|
|
5808
|
-
availability: interactionAvailabilityFromDecision(decision)
|
|
5809
|
-
};
|
|
5810
|
-
if (metadata.kind === "prompt") {
|
|
5811
|
-
return {
|
|
5812
|
-
...baseDescriptor,
|
|
5813
|
-
kind: "prompt",
|
|
5814
|
-
context: promptContext ?? {
|
|
5815
|
-
to: playerId,
|
|
5816
|
-
title: humanizeInteractionId(interactionId)
|
|
5817
|
-
}
|
|
5818
|
-
};
|
|
5819
|
-
}
|
|
5820
|
-
return {
|
|
5821
|
-
...baseDescriptor,
|
|
5822
|
-
kind: "action"
|
|
5823
|
-
};
|
|
5824
|
-
}
|
|
5825
5852
|
function resolveInteractionDecision({
|
|
5826
5853
|
state,
|
|
5827
5854
|
playerId,
|
|
@@ -5856,7 +5883,8 @@ function createInteractionDecisionResolver(scope, stages, authorization) {
|
|
|
5856
5883
|
interaction,
|
|
5857
5884
|
parsedParams: {},
|
|
5858
5885
|
visible: true,
|
|
5859
|
-
descriptor:
|
|
5886
|
+
descriptor: buildInteractionDescriptor(
|
|
5887
|
+
scope,
|
|
5860
5888
|
state,
|
|
5861
5889
|
playerId,
|
|
5862
5890
|
trustedInteractionId,
|
|
@@ -6030,7 +6058,8 @@ function createInteractionDecisionResolver(scope, stages, authorization) {
|
|
|
6030
6058
|
}
|
|
6031
6059
|
const available = stageAllowed && stepAllowed && authorized && !ruleAvailabilityIssue && costAffordable && !authoredValidation;
|
|
6032
6060
|
const unavailableReason = available ? void 0 : !authorized ? "Not your turn" : !stageAllowed ? "Interaction not allowed in current stage" : !stepAllowed ? "Interaction not allowed in current step" : ruleAvailabilityIssue ? ruleAvailabilityIssue.message ?? ruleAvailabilityIssue.errorCode : !costAffordable ? "INSUFFICIENT_RESOURCES" : mode === "card" ? authoredValidation?.message ?? "Interaction unavailable" : "Interaction unavailable";
|
|
6033
|
-
const descriptor =
|
|
6061
|
+
const descriptor = buildInteractionDescriptor(
|
|
6062
|
+
scope,
|
|
6034
6063
|
state,
|
|
6035
6064
|
playerId,
|
|
6036
6065
|
trustedInteractionId,
|
|
@@ -7768,7 +7797,7 @@ function createIngressRuntimeCodec(definition) {
|
|
|
7768
7797
|
},
|
|
7769
7798
|
parseState(rawState) {
|
|
7770
7799
|
const envelope = safeParseOrThrow(
|
|
7771
|
-
ReducerSessionStateSchema,
|
|
7800
|
+
zod_exports.ReducerSessionStateSchema,
|
|
7772
7801
|
rawState,
|
|
7773
7802
|
"state"
|
|
7774
7803
|
);
|
|
@@ -7848,44 +7877,6 @@ function createIngressRuntimeCodec(definition) {
|
|
|
7848
7877
|
};
|
|
7849
7878
|
}
|
|
7850
7879
|
|
|
7851
|
-
// src/generated/reducer-contract/builders.ts
|
|
7852
|
-
function createEffectIdMinter() {
|
|
7853
|
-
let i = 0;
|
|
7854
|
-
return () => `ef${i++}`;
|
|
7855
|
-
}
|
|
7856
|
-
function createEffectBuilders(mint) {
|
|
7857
|
-
return {
|
|
7858
|
-
transition(args, continuation) {
|
|
7859
|
-
const effect = { effectId: mint(), type: "transition", to: args.to };
|
|
7860
|
-
return continuation === void 0 ? effect : Object.assign(effect, { __continuation: continuation });
|
|
7861
|
-
},
|
|
7862
|
-
rollDie(args, continuation) {
|
|
7863
|
-
const effect = { effectId: mint(), type: "rollDie", dieId: args.dieId };
|
|
7864
|
-
return continuation === void 0 ? effect : Object.assign(effect, { __continuation: continuation });
|
|
7865
|
-
},
|
|
7866
|
-
shuffleSharedZone(args, continuation) {
|
|
7867
|
-
const effect = { effectId: mint(), type: "shuffleSharedZone", zoneId: args.zoneId };
|
|
7868
|
-
return continuation === void 0 ? effect : Object.assign(effect, { __continuation: continuation });
|
|
7869
|
-
},
|
|
7870
|
-
shufflePlayerZone(args, continuation) {
|
|
7871
|
-
const effect = { effectId: mint(), type: "shufflePlayerZone", zoneId: args.zoneId, playerId: args.playerId };
|
|
7872
|
-
return continuation === void 0 ? effect : Object.assign(effect, { __continuation: continuation });
|
|
7873
|
-
}
|
|
7874
|
-
};
|
|
7875
|
-
}
|
|
7876
|
-
function materializeAccept(pending) {
|
|
7877
|
-
const effects = [];
|
|
7878
|
-
const continuations = {};
|
|
7879
|
-
for (const pe of pending) {
|
|
7880
|
-
const { __continuation, ...effect } = pe;
|
|
7881
|
-
effects.push(effect);
|
|
7882
|
-
if (__continuation !== void 0) {
|
|
7883
|
-
continuations[effect.effectId] = __continuation;
|
|
7884
|
-
}
|
|
7885
|
-
}
|
|
7886
|
-
return { effects, continuations };
|
|
7887
|
-
}
|
|
7888
|
-
|
|
7889
7880
|
// src/reducer/bundle/ingress-bundle.ts
|
|
7890
7881
|
function routeInteraction(input) {
|
|
7891
7882
|
return {
|
|
@@ -7942,12 +7933,12 @@ function toWireReduceResult(result, serializeState) {
|
|
|
7942
7933
|
message: result.message
|
|
7943
7934
|
};
|
|
7944
7935
|
}
|
|
7945
|
-
const mint = createEffectIdMinter();
|
|
7946
|
-
const fx = createEffectBuilders(mint);
|
|
7936
|
+
const mint = builders_exports.createEffectIdMinter();
|
|
7937
|
+
const fx = builders_exports.createEffectBuilders(mint);
|
|
7947
7938
|
const pending = (result.instructions ?? []).map(
|
|
7948
7939
|
(instruction) => toPendingEffect(instruction, fx)
|
|
7949
7940
|
);
|
|
7950
|
-
const { effects, continuations } = materializeAccept(pending);
|
|
7941
|
+
const { effects, continuations } = builders_exports.materializeAccept(pending);
|
|
7951
7942
|
return {
|
|
7952
7943
|
kind: "accept",
|
|
7953
7944
|
state: serializeState(result.state),
|
|
@@ -7963,8 +7954,8 @@ function toWireDispatchResult(result, serializeState) {
|
|
|
7963
7954
|
message: result.message
|
|
7964
7955
|
};
|
|
7965
7956
|
}
|
|
7966
|
-
const mint = createEffectIdMinter();
|
|
7967
|
-
const fx = createEffectBuilders(mint);
|
|
7957
|
+
const mint = builders_exports.createEffectIdMinter();
|
|
7958
|
+
const fx = builders_exports.createEffectBuilders(mint);
|
|
7968
7959
|
const trace = [];
|
|
7969
7960
|
for (const entry of result.trace) {
|
|
7970
7961
|
switch (entry.type) {
|
|
@@ -7997,7 +7988,7 @@ function toWireDispatchResult(result, serializeState) {
|
|
|
7997
7988
|
entry.instruction,
|
|
7998
7989
|
fx
|
|
7999
7990
|
);
|
|
8000
|
-
const { effects, continuations } = materializeAccept([
|
|
7991
|
+
const { effects, continuations } = builders_exports.materializeAccept([
|
|
8001
7992
|
pending
|
|
8002
7993
|
]);
|
|
8003
7994
|
const [wireEffect] = effects;
|