dreamboard 0.1.16 → 0.1.18

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.
@@ -14098,6 +14098,9 @@ var ProjectSeatsDynamicRequestSchema = external_exports.object({ "state": Reduce
14098
14098
  var BoardStaticProjectionSchema = external_exports.object({ "view": JsonValueSchema, "hash": external_exports.string().min(1), "manifestVersion": external_exports.string() }).strict();
14099
14099
 
14100
14100
  // ../../packages/app-sdk/src/reducer/per-player.ts
14101
+ function asPlayerId(raw) {
14102
+ return raw;
14103
+ }
14101
14104
  function perPlayerGet(value, id) {
14102
14105
  for (const [candidate, v] of value.entries) {
14103
14106
  if (candidate === id) {
@@ -14207,6 +14210,45 @@ function resolveDomainChoices(choices, context) {
14207
14210
  disabledReason: choice.disabledReason
14208
14211
  }));
14209
14212
  }
14213
+ function resolveDependentDomainChoices(choices, context) {
14214
+ const resolved = typeof choices === "function" ? choices(context) : choices;
14215
+ return resolved.map((choice) => ({
14216
+ value: choice.value,
14217
+ label: choice.label,
14218
+ icon: choice.icon,
14219
+ badge: choice.badge,
14220
+ description: choice.description,
14221
+ disabled: choice.disabled,
14222
+ disabledReason: choice.disabledReason
14223
+ }));
14224
+ }
14225
+ function choiceValuesInclude(choices, value) {
14226
+ return choices.some((choice) => Object.is(choice.value, value));
14227
+ }
14228
+ function assertChoiceDefaultInChoices(inputName, choices, defaultValue) {
14229
+ if (choiceValuesInclude(choices, defaultValue)) return;
14230
+ const printable = defaultValue === null ? "null" : `'${defaultValue}'`;
14231
+ throw new Error(
14232
+ `${inputName} defaultValue ${printable} must be one of its choices. If null is a valid value, add an explicit { value: null, label: ... } choice.`
14233
+ );
14234
+ }
14235
+ function choiceSchema(choices) {
14236
+ const values = choices.map((choice) => choice.value);
14237
+ const stringValues = values.filter(
14238
+ (value) => value !== null
14239
+ );
14240
+ const hasNull = values.some((value) => value === null);
14241
+ if (stringValues.length === 0) {
14242
+ return external_exports.null();
14243
+ }
14244
+ const stringSchema = external_exports.enum(
14245
+ stringValues
14246
+ );
14247
+ if (hasNull) {
14248
+ return external_exports.union([stringSchema, external_exports.null()]);
14249
+ }
14250
+ return stringSchema;
14251
+ }
14210
14252
  function resolveResourceMapChoices(choices, context) {
14211
14253
  const resources = context.state.table.resources;
14212
14254
  const firstResourceMap = isPerPlayer(resources) && resources.entries.length > 0 ? resources.entries[0]?.[1] : resources;
@@ -14243,7 +14285,13 @@ function resourceMapInput(options) {
14243
14285
  schema: external_exports.record(external_exports.string(), external_exports.number().int().nonnegative()),
14244
14286
  ..."defaultValue" in options ? { defaultValue: options.defaultValue } : {},
14245
14287
  domain: (state, playerId, q, derived) => {
14246
- const context = { state, playerId, q, derived };
14288
+ const context = {
14289
+ state,
14290
+ playerId,
14291
+ q,
14292
+ derived,
14293
+ values: {}
14294
+ };
14247
14295
  return {
14248
14296
  type: "resourceMap",
14249
14297
  resources: options.resources.map((resource) => ({
@@ -14263,7 +14311,13 @@ function numberInput(options) {
14263
14311
  schema: external_exports.number(),
14264
14312
  ..."defaultValue" in options ? { defaultValue: options.defaultValue } : {},
14265
14313
  domain: (state, playerId, q, derived) => {
14266
- const context = { state, playerId, q, derived };
14314
+ const context = {
14315
+ state,
14316
+ playerId,
14317
+ q,
14318
+ derived,
14319
+ values: {}
14320
+ };
14267
14321
  return {
14268
14322
  type: "boundedNumber",
14269
14323
  min: resolveDomainNumber(options.min, context, 0),
@@ -14274,23 +14328,80 @@ function numberInput(options) {
14274
14328
  };
14275
14329
  }
14276
14330
  function choiceInput(options) {
14331
+ const dependsOn = options.dependsOn?.map((dependency) => dependency.key);
14277
14332
  if (Array.isArray(options.choices) && options.choices.length === 0) {
14278
14333
  throw new Error("formInput.choice requires at least one choice.");
14279
14334
  }
14280
- const schema = Array.isArray(options.choices) ? external_exports.enum(
14281
- options.choices.map((choice) => choice.value)
14282
- ) : external_exports.string();
14335
+ const staticChoices = Array.isArray(options.choices) ? options.choices : null;
14336
+ const hasStaticDefault = typeof options.defaultValue !== "function";
14337
+ const staticDefault = options.defaultValue;
14338
+ if (staticChoices && hasStaticDefault) {
14339
+ assertChoiceDefaultInChoices(
14340
+ "formInput.choice",
14341
+ staticChoices,
14342
+ staticDefault
14343
+ );
14344
+ }
14345
+ const schema = staticChoices ? choiceSchema(staticChoices) : external_exports.string().nullable();
14346
+ const dynamicDefault = typeof options.defaultValue === "function" ? options.defaultValue : void 0;
14283
14347
  return {
14284
14348
  kind: "form",
14285
14349
  schema,
14286
- ..."defaultValue" in options ? { defaultValue: options.defaultValue } : {},
14287
- domain: (state, playerId, q, derived) => {
14288
- const context = { state, playerId, q, derived };
14350
+ ...hasStaticDefault ? { defaultValue: staticDefault } : {},
14351
+ ...dependsOn ? { dependsOn } : {},
14352
+ domain: (state, playerId, q, derived, values) => {
14353
+ const context = {
14354
+ state,
14355
+ playerId,
14356
+ q,
14357
+ derived
14358
+ };
14359
+ const choices = dependsOn ? resolveDependentDomainChoices(
14360
+ options.choices,
14361
+ {
14362
+ ...context,
14363
+ values: values ?? {}
14364
+ }
14365
+ ) : resolveDomainChoices(options.choices, {
14366
+ ...context,
14367
+ values: {}
14368
+ });
14369
+ if (hasStaticDefault) {
14370
+ assertChoiceDefaultInChoices(
14371
+ "formInput.choice",
14372
+ choices,
14373
+ staticDefault
14374
+ );
14375
+ }
14289
14376
  return {
14290
14377
  type: "choice",
14291
- choices: resolveDomainChoices(options.choices, context)
14378
+ choices
14292
14379
  };
14293
- }
14380
+ },
14381
+ ...dynamicDefault ? {
14382
+ resolveDefaultValue: (state, playerId, q, derived, domain) => {
14383
+ const choices = domain.type === "choice" ? domain.choices.map((choice) => ({
14384
+ value: choice.value,
14385
+ label: choice.label,
14386
+ icon: choice.icon,
14387
+ badge: choice.badge,
14388
+ description: choice.description,
14389
+ disabled: choice.disabled,
14390
+ disabledReason: choice.disabledReason
14391
+ })) : [];
14392
+ const resolved = dynamicDefault({
14393
+ state,
14394
+ playerId,
14395
+ q,
14396
+ derived,
14397
+ values: {},
14398
+ choices
14399
+ });
14400
+ if (resolved === void 0) return void 0;
14401
+ assertChoiceDefaultInChoices("formInput.choice", choices, resolved);
14402
+ return resolved;
14403
+ }
14404
+ } : {}
14294
14405
  };
14295
14406
  }
14296
14407
  function choiceListInput(options) {
@@ -14302,10 +14413,21 @@ function choiceListInput(options) {
14302
14413
  return {
14303
14414
  kind: "form",
14304
14415
  schema: external_exports.array(external_exports.string()),
14305
- ...staticDefaultValue ? { defaultValue: staticDefaultValue } : {},
14416
+ ...staticDefaultValue !== void 0 ? { defaultValue: staticDefaultValue } : {},
14306
14417
  domain: (state, playerId, q, derived) => {
14307
- const context = { state, playerId, q, derived };
14308
- const choices = resolveDomainChoices(options.choices, context);
14418
+ const context = {
14419
+ state,
14420
+ playerId,
14421
+ q,
14422
+ derived,
14423
+ values: {}
14424
+ };
14425
+ const choices = resolveDomainChoices(options.choices, context).map(
14426
+ (choice) => ({
14427
+ ...choice,
14428
+ value: choice.value
14429
+ })
14430
+ );
14309
14431
  return {
14310
14432
  type: "choiceList",
14311
14433
  choices,
@@ -14332,12 +14454,25 @@ function choiceListInput(options) {
14332
14454
  playerId,
14333
14455
  q,
14334
14456
  derived,
14457
+ values: {},
14335
14458
  choices
14336
14459
  });
14337
14460
  }
14338
14461
  } : {}
14339
14462
  };
14340
14463
  }
14464
+ function formInputForState() {
14465
+ return Object.assign(
14466
+ ((schema, options) => baseFormInput(schema, options)),
14467
+ {
14468
+ resourceMap: (options) => resourceMapInput(options),
14469
+ resourceChoices: (options) => formInput.resourceChoices(options),
14470
+ number: (options) => numberInput(options),
14471
+ choice: (options) => choiceInput(options),
14472
+ choiceList: (options) => choiceListInput(options)
14473
+ }
14474
+ );
14475
+ }
14341
14476
  var formInput = Object.assign(baseFormInput, {
14342
14477
  resourceMap: resourceMapInput,
14343
14478
  resourceChoices: (options) => ({
@@ -14346,32 +14481,49 @@ var formInput = Object.assign(baseFormInput, {
14346
14481
  }),
14347
14482
  number: numberInput,
14348
14483
  choice: choiceInput,
14349
- choiceList: choiceListInput
14484
+ choiceList: choiceListInput,
14485
+ forState: formInputForState
14350
14486
  });
14351
14487
 
14352
14488
  // ../../packages/app-sdk/src/reducer/inputs/boardInput.ts
14353
14489
  function makeBoardCollector(kind) {
14354
14490
  return function collector(options) {
14355
14491
  const target = options.target;
14492
+ const dependsOn = options.dependsOn?.map((dependency) => dependency.key);
14356
14493
  return {
14357
14494
  kind,
14358
14495
  schema: external_exports.string(),
14359
- eligibleTargets: ((state, playerId, q) => target.eligible({
14496
+ eligibleTargets: ((state, playerId, q, values) => target.eligible({
14360
14497
  state,
14361
14498
  playerId,
14362
- q
14499
+ q,
14500
+ values
14363
14501
  })),
14364
- validateTarget: ((state, playerId, q, targetId) => target.validate(
14502
+ validateTarget: ((state, playerId, q, targetId, values) => target.validate(
14365
14503
  {
14366
14504
  state,
14367
14505
  playerId,
14368
- q
14506
+ q,
14507
+ values
14369
14508
  },
14370
14509
  targetId
14371
14510
  )),
14511
+ ...dependsOn ? { dependsOn } : {},
14512
+ domain: dependsOn ? (state, playerId, q, _derived, values) => ({
14513
+ type: "target",
14514
+ targetKind: target.targetKind,
14515
+ boardId: target.boardId,
14516
+ eligibleTargets: target.eligible({
14517
+ state,
14518
+ playerId,
14519
+ q,
14520
+ values
14521
+ }).map(String)
14522
+ }) : void 0,
14372
14523
  meta: {
14373
14524
  targetKind: target.targetKind,
14374
- boardId: target.boardId
14525
+ boardId: target.boardId,
14526
+ valueKind: target.valueKind
14375
14527
  }
14376
14528
  };
14377
14529
  };
@@ -14388,12 +14540,13 @@ var DEFAULT_MISSING_CANDIDATE_ISSUE = {
14388
14540
  };
14389
14541
  function createTargetRule(candidates, predicates, options = {}) {
14390
14542
  const missingCandidateIssue = options.missingCandidateIssue ?? DEFAULT_MISSING_CANDIDATE_ISSUE;
14391
- const validate2 = (ctx, id) => {
14392
- if (!candidates(ctx).includes(id)) {
14543
+ const equals = options.equals ?? Object.is;
14544
+ const validate2 = (ctx, target) => {
14545
+ if (!candidates(ctx).some((candidate) => equals(candidate, target))) {
14393
14546
  return missingCandidateIssue;
14394
14547
  }
14395
14548
  for (const predicate of predicates) {
14396
- if (!predicate.test({ ...ctx, targetId: id })) {
14549
+ if (!predicate.test({ ...ctx, targetId: target, target })) {
14397
14550
  return {
14398
14551
  errorCode: predicate.errorCode,
14399
14552
  message: predicate.message
@@ -14405,7 +14558,7 @@ function createTargetRule(candidates, predicates, options = {}) {
14405
14558
  const rule = {
14406
14559
  eligible: (ctx) => candidates(ctx).filter((targetId) => validate2(ctx, targetId) == null),
14407
14560
  validate: validate2,
14408
- isEligible: (ctx, id) => validate2(ctx, id) == null,
14561
+ isEligible: (ctx, target) => validate2(ctx, target) == null,
14409
14562
  bind: (ctx) => ({
14410
14563
  eligible: () => rule.eligible(ctx),
14411
14564
  validate: (id) => rule.validate(ctx, id),
@@ -14429,7 +14582,7 @@ function candidateIdsForKind(q, boardId, targetKind) {
14429
14582
  if (targetKind === "vertex") {
14430
14583
  return idsFromCollection(q.board.tiled(boardId).vertices);
14431
14584
  }
14432
- return idsFromCollection(q.board.get(boardId).spaces);
14585
+ return idsFromCollection(q.board.get(boardId)?.spaces);
14433
14586
  }
14434
14587
  function idsFromCollection(collection) {
14435
14588
  if (!collection) return [];
@@ -14456,10 +14609,47 @@ function createBoardTargetBuilder(targetKind, boardId) {
14456
14609
  }
14457
14610
  ),
14458
14611
  boardId,
14459
- targetKind
14612
+ targetKind,
14613
+ valueKind: "board-id"
14614
+ })
14615
+ );
14616
+ }
14617
+ function createPlayerSpaceTargetBuilder(boardId) {
14618
+ return createTargetRuleBuilder(
14619
+ (predicates) => ({
14620
+ ...createTargetRule(
14621
+ ({ state, q }) => {
14622
+ const spacesForPlayer = (playerId) => candidateIdsForKind(
14623
+ q,
14624
+ `${boardId}:${playerId}`,
14625
+ "space"
14626
+ );
14627
+ return state.table.playerOrder.flatMap(
14628
+ (playerId) => spacesForPlayer(playerId).map((spaceId) => ({
14629
+ boardId,
14630
+ playerId,
14631
+ spaceId
14632
+ }))
14633
+ );
14634
+ },
14635
+ predicates,
14636
+ {
14637
+ missingCandidateIssue: {
14638
+ errorCode: "BOARD_TARGET_NOT_ELIGIBLE",
14639
+ message: "Board target is not eligible."
14640
+ },
14641
+ equals: (left, right) => isPlayerBoardSpaceTarget(left) && isPlayerBoardSpaceTarget(right) && left.boardId === right.boardId && left.playerId === right.playerId && left.spaceId === right.spaceId
14642
+ }
14643
+ ),
14644
+ boardId,
14645
+ targetKind: "space",
14646
+ valueKind: "player-board-space"
14460
14647
  })
14461
14648
  );
14462
14649
  }
14650
+ function isPlayerBoardSpaceTarget(value) {
14651
+ return typeof value === "object" && value !== null && "boardId" in value && "playerId" in value && "spaceId" in value;
14652
+ }
14463
14653
  function makeBoardTargetFactory(targetKind) {
14464
14654
  return function target(boardId) {
14465
14655
  return createBoardTargetBuilder(targetKind, boardId);
@@ -14469,7 +14659,10 @@ var boardTarget = {
14469
14659
  edge: makeBoardTargetFactory("edge"),
14470
14660
  vertex: makeBoardTargetFactory("vertex"),
14471
14661
  space: makeBoardTargetFactory("space"),
14472
- tile: makeBoardTargetFactory("tile")
14662
+ tile: makeBoardTargetFactory("tile"),
14663
+ playerSpace(boardId) {
14664
+ return createPlayerSpaceTargetBuilder(boardId);
14665
+ }
14473
14666
  };
14474
14667
 
14475
14668
  // ../../packages/app-sdk/src/reducer/inputs/cardTarget.ts
@@ -14516,22 +14709,38 @@ var cardTarget = {
14516
14709
  // ../../packages/app-sdk/src/reducer/inputs/cardInput.ts
14517
14710
  function cardInput(options) {
14518
14711
  const target = options.target;
14712
+ const dependsOn = options.dependsOn?.map((dependency) => dependency.key);
14519
14713
  return {
14520
14714
  kind: "card",
14521
14715
  schema: external_exports.string(),
14522
- eligibleTargets: ((state, playerId, q) => target.eligible({
14716
+ eligibleTargets: ((state, playerId, q, values) => target.eligible({
14523
14717
  state,
14524
14718
  playerId,
14525
- q
14719
+ q,
14720
+ values
14526
14721
  })),
14527
- validateTarget: ((state, playerId, q, targetId) => target.validate(
14722
+ validateTarget: ((state, playerId, q, targetId, values) => target.validate(
14528
14723
  {
14529
14724
  state,
14530
14725
  playerId,
14531
- q
14726
+ q,
14727
+ values
14532
14728
  },
14533
14729
  targetId
14534
14730
  )),
14731
+ ...dependsOn ? { dependsOn } : {},
14732
+ domain: dependsOn ? (state, playerId, q, _derived, values) => ({
14733
+ type: "target",
14734
+ targetKind: target.targetKind,
14735
+ zoneId: target.zoneId,
14736
+ zoneIds: target.zoneIds,
14737
+ eligibleTargets: target.eligible({
14738
+ state,
14739
+ playerId,
14740
+ q,
14741
+ values
14742
+ }).map(String)
14743
+ }) : void 0,
14535
14744
  meta: {
14536
14745
  zoneId: target.zoneId,
14537
14746
  zoneIds: target.zoneIds,
@@ -16223,6 +16432,35 @@ function shuffleWithRng(values, rng, operation = "shuffleSharedZone") {
16223
16432
  }
16224
16433
  return { orderedValues, nextRng, consumptions };
16225
16434
  }
16435
+ function subsetWithRng(values, count, rng) {
16436
+ if (!Number.isInteger(count) || count < 0) {
16437
+ throw new Error("random.subset count must be a non-negative integer.");
16438
+ }
16439
+ if (count > values.length) {
16440
+ throw new Error(
16441
+ `random.subset count ${count} exceeds source length ${values.length}.`
16442
+ );
16443
+ }
16444
+ const shuffled = shuffleWithRng(values, rng, "randomSubset");
16445
+ return {
16446
+ values: shuffled.orderedValues.slice(0, count),
16447
+ nextRng: shuffled.nextRng,
16448
+ consumptions: shuffled.consumptions
16449
+ };
16450
+ }
16451
+ function createMutableRandomHelpers(rng) {
16452
+ let current = rng;
16453
+ return {
16454
+ random: {
16455
+ subset(options) {
16456
+ const sampled = subsetWithRng(options.from, options.count, current);
16457
+ current = sampled.nextRng;
16458
+ return sampled.values;
16459
+ }
16460
+ },
16461
+ currentRng: () => current
16462
+ };
16463
+ }
16226
16464
  function sampleRngCollectorValue(collector, rng) {
16227
16465
  const meta = collector.meta;
16228
16466
  switch (meta.rng) {
@@ -16671,6 +16909,126 @@ function createReducerFx(_state) {
16671
16909
  function updateTable(state, nextTable) {
16672
16910
  return { ...state, table: nextTable };
16673
16911
  }
16912
+ function computePlayerZoneVisibility(table, zoneId, playerId) {
16913
+ const mode = table.handVisibility[zoneId];
16914
+ if (mode === "all" || mode === "public") {
16915
+ return { faceUp: true };
16916
+ }
16917
+ return { faceUp: false, visibleTo: [playerId] };
16918
+ }
16919
+ function readPlayerZoneCards(table, zoneId, playerId) {
16920
+ const zone = table.zones.perPlayer[zoneId] ?? table.hands[zoneId];
16921
+ if (!zone) {
16922
+ throw new Error(`Player zone '${zoneId}' does not exist.`);
16923
+ }
16924
+ return perPlayerGet(zone, asPlayerId(playerId)) ?? [];
16925
+ }
16926
+ function writePlayerZoneCards(table, zoneId, playerId, cards) {
16927
+ const currentZone = table.zones.perPlayer[zoneId];
16928
+ const currentHand = table.hands[zoneId];
16929
+ const player = asPlayerId(playerId);
16930
+ if (currentZone) {
16931
+ table.zones.perPlayer[zoneId] = perPlayerSet(
16932
+ currentZone,
16933
+ player,
16934
+ [...cards]
16935
+ );
16936
+ }
16937
+ if (currentHand) {
16938
+ table.hands[zoneId] = perPlayerSet(
16939
+ currentHand,
16940
+ player,
16941
+ [...cards]
16942
+ );
16943
+ }
16944
+ }
16945
+ function assertCardAllowedInPlayerZone(table, zoneId, cardId) {
16946
+ const allowedCardSetIds = table.zones.cardSetIdsByZoneId?.[zoneId];
16947
+ if (!allowedCardSetIds || allowedCardSetIds.length === 0) {
16948
+ return;
16949
+ }
16950
+ const card = table.cards[cardId];
16951
+ if (!card) {
16952
+ throw new Error(`Card '${cardId}' does not exist.`);
16953
+ }
16954
+ if (!allowedCardSetIds.includes(card.cardSetId)) {
16955
+ throw new Error(
16956
+ `Card '${cardId}' from set '${card.cardSetId}' is not allowed in player zone '${zoneId}'.`
16957
+ );
16958
+ }
16959
+ }
16960
+ function rotatePlayerZoneTable(options) {
16961
+ const nextTable = cloneRuntimeTable(options.table);
16962
+ const zoneId = options.zoneId;
16963
+ if (!nextTable.zones.perPlayer[zoneId] && !nextTable.hands[zoneId]) {
16964
+ throw new Error(`Player zone '${zoneId}' does not exist.`);
16965
+ }
16966
+ const players = [...options.players ?? nextTable.playerOrder];
16967
+ if (players.length === 0) {
16968
+ return nextTable;
16969
+ }
16970
+ const playerSet = new Set(nextTable.playerOrder);
16971
+ for (const playerId of players) {
16972
+ if (!playerSet.has(playerId)) {
16973
+ throw new Error(
16974
+ `Cannot rotate player zone '${zoneId}': player '${playerId}' is not in player order.`
16975
+ );
16976
+ }
16977
+ }
16978
+ const selectedByPlayer = /* @__PURE__ */ new Map();
16979
+ for (const playerId of players) {
16980
+ const sourceCards = readPlayerZoneCards(nextTable, zoneId, playerId);
16981
+ const selected = options.cardIdsByPlayer?.[playerId] ?? sourceCards;
16982
+ for (const cardId of selected) {
16983
+ if (!sourceCards.includes(cardId)) {
16984
+ throw new Error(
16985
+ `Cannot rotate player zone '${zoneId}': card '${cardId}' is not in zone for player '${playerId}'.`
16986
+ );
16987
+ }
16988
+ assertCardAllowedInPlayerZone(nextTable, zoneId, cardId);
16989
+ }
16990
+ selectedByPlayer.set(playerId, [...selected]);
16991
+ }
16992
+ const removeByPlayer = /* @__PURE__ */ new Map();
16993
+ for (const playerId of players) {
16994
+ const selected = new Set(selectedByPlayer.get(playerId) ?? []);
16995
+ removeByPlayer.set(
16996
+ playerId,
16997
+ readPlayerZoneCards(nextTable, zoneId, playerId).filter(
16998
+ (cardId) => !selected.has(cardId)
16999
+ )
17000
+ );
17001
+ }
17002
+ const additionsByPlayer = new Map(
17003
+ players.map((playerId) => [playerId, []])
17004
+ );
17005
+ for (const [index, fromPlayerId] of players.entries()) {
17006
+ const offset = options.direction === "left" ? 1 : -1;
17007
+ const recipient = players[(index + offset + players.length) % players.length];
17008
+ additionsByPlayer.get(recipient).push(...selectedByPlayer.get(fromPlayerId) ?? []);
17009
+ }
17010
+ for (const playerId of players) {
17011
+ const remaining = removeByPlayer.get(playerId) ?? [];
17012
+ const additions = additionsByPlayer.get(playerId) ?? [];
17013
+ const nextCards = options.position === "top" ? [...additions, ...remaining] : [...remaining, ...additions];
17014
+ writePlayerZoneCards(nextTable, zoneId, playerId, nextCards);
17015
+ for (const [position, cardId] of nextCards.entries()) {
17016
+ nextTable.componentLocations[cardId] = {
17017
+ type: "InHand",
17018
+ handId: zoneId,
17019
+ playerId,
17020
+ position
17021
+ };
17022
+ nextTable.ownerOfCard[cardId] = playerId;
17023
+ nextTable.visibility[cardId] = computePlayerZoneVisibility(
17024
+ nextTable,
17025
+ zoneId,
17026
+ playerId
17027
+ );
17028
+ }
17029
+ }
17030
+ return nextTable;
17031
+ }
16674
17032
  var moveComponentToEdgeInternal = moveComponentToEdge;
16675
17033
  var moveComponentToVertexInternal = moveComponentToVertex;
16676
17034
  var dealCardsFromDeckToHandInternal = dealCardsFromDeckToHand;
@@ -16854,6 +17212,19 @@ function createReducerOps() {
16854
17212
  return updateTable(state, nextTable);
16855
17213
  };
16856
17214
  },
17215
+ rotatePlayerZone(args) {
17216
+ return (state) => {
17217
+ const nextTable = rotatePlayerZoneTable({
17218
+ table: state.table,
17219
+ zoneId: args.zoneId,
17220
+ direction: args.direction,
17221
+ players: args.players,
17222
+ cardIdsByPlayer: args.cardIdsByPlayer,
17223
+ position: args.position ?? "bottom"
17224
+ });
17225
+ return updateTable(state, nextTable);
17226
+ };
17227
+ },
16857
17228
  moveComponentToSpace(args) {
16858
17229
  return (state) => {
16859
17230
  const nextTable = moveComponentToSpace(
@@ -16953,6 +17324,47 @@ function createReducerOps() {
16953
17324
  return impl;
16954
17325
  }
16955
17326
 
17327
+ // ../../packages/app-sdk/src/reducer/transaction.ts
17328
+ function createReducerTransaction(initialState, ops = createReducerOps()) {
17329
+ let currentState = initialState;
17330
+ let currentQueries = createStateQueries(currentState);
17331
+ const refresh = (nextState) => {
17332
+ currentState = nextState;
17333
+ currentQueries = createStateQueries(currentState);
17334
+ return currentState;
17335
+ };
17336
+ const apply = (op) => refresh(op(currentState));
17337
+ const base = {
17338
+ get state() {
17339
+ return currentState;
17340
+ },
17341
+ get q() {
17342
+ return currentQueries;
17343
+ },
17344
+ apply
17345
+ };
17346
+ return new Proxy(base, {
17347
+ get(target, property, receiver) {
17348
+ if (property in target) {
17349
+ return Reflect.get(target, property, receiver);
17350
+ }
17351
+ const opFactory = ops[property];
17352
+ if (typeof opFactory !== "function") {
17353
+ return void 0;
17354
+ }
17355
+ return (...args) => {
17356
+ const op = opFactory(
17357
+ ...args
17358
+ );
17359
+ return apply(op);
17360
+ };
17361
+ }
17362
+ });
17363
+ }
17364
+ function createReducerEdit(ops = createReducerOps()) {
17365
+ return (state) => createReducerTransaction(state, ops);
17366
+ }
17367
+
16956
17368
  // ../../packages/app-sdk/src/reducer/definition-index.ts
16957
17369
  function phaseEntriesOf(definition) {
16958
17370
  return Object.entries(definition.phases);
@@ -17001,6 +17413,7 @@ function collectReducerDefinitionIndex(definition) {
17001
17413
  cardActionId,
17002
17414
  {
17003
17415
  ...cardAction,
17416
+ __steps: cardAction.__steps,
17004
17417
  inputs: {
17005
17418
  cardId: cardInput({
17006
17419
  target: cardTarget.zones([cardAction.playFrom]).where({
@@ -17078,7 +17491,7 @@ function buildContext(state, manifest) {
17078
17491
  manifest,
17079
17492
  playerOrder: [...state.table.playerOrder],
17080
17493
  activePlayers: [...state.flow.activePlayers],
17081
- runtime: state.runtime,
17494
+ runtime: publicRuntime(state.runtime),
17082
17495
  setup: state.runtime.setup ? {
17083
17496
  profileId: state.runtime.setup.profileId,
17084
17497
  optionValues: {
@@ -17087,6 +17500,17 @@ function buildContext(state, manifest) {
17087
17500
  } : null
17088
17501
  };
17089
17502
  }
17503
+ function publicRuntime(runtime) {
17504
+ const { rng: _rng, ...rest } = runtime;
17505
+ return rest;
17506
+ }
17507
+ var DISABLED_RANDOM_HELPERS = {
17508
+ subset() {
17509
+ throw new Error(
17510
+ "random helpers are only available in reducer mutation callbacks."
17511
+ );
17512
+ }
17513
+ };
17090
17514
  function buildRuntimeArgs(state, manifest, helpers, toDomainState2, extra, options = {}) {
17091
17515
  const domainState = toDomainState2(state);
17092
17516
  const q = options.q ?? createStateQueries(domainState);
@@ -17096,7 +17520,8 @@ function buildRuntimeArgs(state, manifest, helpers, toDomainState2, extra, optio
17096
17520
  fx: options.fx ?? fxForState(state),
17097
17521
  q,
17098
17522
  derived: options.derived ?? createDerivedResolver(domainState, { q }),
17099
- runtime: state.runtime,
17523
+ runtime: publicRuntime(state.runtime),
17524
+ random: options.random ?? DISABLED_RANDOM_HELPERS,
17100
17525
  ...extra
17101
17526
  };
17102
17527
  }
@@ -17130,13 +17555,16 @@ var runtimeResultHelpers = {
17130
17555
  // ../../packages/app-sdk/src/reducer/bundle/trusted/trusted-state-codec.ts
17131
17556
  function toDomainState(state) {
17132
17557
  const { runtime: _runtime, ...domain } = state;
17558
+ attachPhaseAccessor(domain);
17133
17559
  return domain;
17134
17560
  }
17135
17561
  function toCombinedState(session) {
17136
- return {
17562
+ const combined = {
17137
17563
  ...session.domain,
17138
17564
  runtime: session.runtime
17139
17565
  };
17566
+ attachPhaseAccessor(combined);
17567
+ return combined;
17140
17568
  }
17141
17569
  function toSessionState(state, toDomain) {
17142
17570
  return {
@@ -17144,6 +17572,19 @@ function toSessionState(state, toDomain) {
17144
17572
  runtime: state.runtime
17145
17573
  };
17146
17574
  }
17575
+ function attachPhaseAccessor(state) {
17576
+ if (!state || typeof state !== "object") return;
17577
+ const candidate = state;
17578
+ const phase = candidate.phase;
17579
+ if (!phase || typeof phase !== "object") return;
17580
+ const descriptor = Object.getOwnPropertyDescriptor(phase, "get");
17581
+ if (descriptor && typeof descriptor.value === "function") return;
17582
+ Object.defineProperty(phase, "get", {
17583
+ enumerable: false,
17584
+ configurable: true,
17585
+ value: (phaseName) => candidate.flow?.currentPhase === phaseName ? phase : null
17586
+ });
17587
+ }
17147
17588
 
17148
17589
  // ../../packages/app-sdk/src/reducer/bundle/trusted/trusted-setup-profiles.ts
17149
17590
  function resolveTrustedSetupProfiles(definition) {
@@ -17225,7 +17666,8 @@ function createTrustedRuntimeScope(definition) {
17225
17666
  }
17226
17667
  const helpers = {
17227
17668
  ...runtimeResultHelpers,
17228
- ops: createReducerOps()
17669
+ ops: createReducerOps(),
17670
+ edit: createReducerEdit()
17229
17671
  };
17230
17672
  function fxForState2(state) {
17231
17673
  return fxForState(state);
@@ -17288,24 +17730,31 @@ function createTrustedInstructionRunner(scope, interactions, lifecycle) {
17288
17730
  }
17289
17731
  const parsed = interactions.parseInteractionParams(
17290
17732
  interaction,
17291
- input.params
17733
+ input.params,
17734
+ { playerId: input.playerId }
17292
17735
  );
17293
17736
  if (!parsed.ok) {
17294
17737
  return rejectResult("invalid-action-params", parsed.message);
17295
17738
  }
17296
- return normalizeResult(
17739
+ const random = createMutableRandomHelpers(state.runtime.rng);
17740
+ const result = normalizeResult(
17297
17741
  interaction.reduce(
17298
- scope.buildRuntimeArgs(state, {
17299
- ...ctx,
17300
- state: scope.toDomainState(state),
17301
- input: {
17302
- playerId: input.playerId,
17303
- params: parsed.params
17304
- }
17305
- })
17742
+ scope.buildRuntimeArgs(
17743
+ state,
17744
+ {
17745
+ ...ctx,
17746
+ state: scope.toDomainState(state),
17747
+ input: {
17748
+ playerId: input.playerId,
17749
+ params: parsed.params
17750
+ }
17751
+ },
17752
+ { random: random.random }
17753
+ )
17306
17754
  ),
17307
17755
  scope.toDomainState(state)
17308
17756
  );
17757
+ return result.type === "accept" ? { ...result, runtimeRng: random.currentRng() } : result;
17309
17758
  }
17310
17759
  if (input.kind === "continuation") {
17311
17760
  const continuation = scope.continuationById(input.continuationId);
@@ -17315,21 +17764,27 @@ function createTrustedInstructionRunner(scope, interactions, lifecycle) {
17315
17764
  `Continuation '${input.continuationId}' was not registered.`
17316
17765
  );
17317
17766
  }
17318
- return normalizeResult(
17767
+ const random = createMutableRandomHelpers(state.runtime.rng);
17768
+ const result = normalizeResult(
17319
17769
  continuation.reduce(
17320
- scope.buildRuntimeArgs(state, {
17321
- ...ctx,
17322
- state: scope.toDomainState(state),
17323
- input: {
17324
- source: "effect",
17325
- effectKind: input.effectKind,
17326
- data: input.resumeData,
17327
- response: input.response
17328
- }
17329
- })
17770
+ scope.buildRuntimeArgs(
17771
+ state,
17772
+ {
17773
+ ...ctx,
17774
+ state: scope.toDomainState(state),
17775
+ input: {
17776
+ source: "effect",
17777
+ effectKind: input.effectKind,
17778
+ data: input.resumeData,
17779
+ response: input.response
17780
+ }
17781
+ },
17782
+ { random: random.random }
17783
+ )
17330
17784
  ),
17331
17785
  scope.toDomainState(state)
17332
17786
  );
17787
+ return result.type === "accept" ? { ...result, runtimeRng: random.currentRng() } : result;
17333
17788
  }
17334
17789
  return scope.runtimeHelpers.accept(scope.toDomainState(state));
17335
17790
  }
@@ -17461,14 +17916,19 @@ function createTrustedInstructionRunner(scope, interactions, lifecycle) {
17461
17916
  }
17462
17917
  ])
17463
17918
  );
17919
+ const random = createMutableRandomHelpers(stateWithSubmission.runtime.rng);
17464
17920
  const resolved = normalizeResult(
17465
17921
  resolve(
17466
- scope.buildRuntimeArgs(stateWithSubmission, {
17467
- state: scope.toDomainState(stateWithSubmission),
17468
- submissions: resolvedSubmissions,
17469
- submittedPlayerIds: [...actors],
17470
- waitingPlayerIds: []
17471
- })
17922
+ scope.buildRuntimeArgs(
17923
+ stateWithSubmission,
17924
+ {
17925
+ state: scope.toDomainState(stateWithSubmission),
17926
+ submissions: resolvedSubmissions,
17927
+ submittedPlayerIds: [...actors],
17928
+ waitingPlayerIds: []
17929
+ },
17930
+ { random: random.random }
17931
+ )
17472
17932
  ),
17473
17933
  scope.toDomainState(stateWithSubmission)
17474
17934
  );
@@ -17479,7 +17939,7 @@ function createTrustedInstructionRunner(scope, interactions, lifecycle) {
17479
17939
  type: "accept",
17480
17940
  state: clearSimultaneousCurrent({
17481
17941
  ...resolved.state,
17482
- runtime: stateWithSubmission.runtime
17942
+ runtime: { ...stateWithSubmission.runtime, rng: random.currentRng() }
17483
17943
  }),
17484
17944
  instructions: resolved.instructions ?? []
17485
17945
  };
@@ -17501,7 +17961,10 @@ function createTrustedInstructionRunner(scope, interactions, lifecycle) {
17501
17961
  type: "accept",
17502
17962
  state: {
17503
17963
  ...result.state,
17504
- runtime: sampled.state.runtime
17964
+ runtime: {
17965
+ ...sampled.state.runtime,
17966
+ rng: result.runtimeRng ?? sampled.state.runtime.rng
17967
+ }
17505
17968
  },
17506
17969
  instructions: result.instructions ?? []
17507
17970
  };
@@ -17596,6 +18059,48 @@ function withSelection(domain, collector) {
17596
18059
  if (!collector.selection) return domain;
17597
18060
  return { ...domain, selection: collector.selection };
17598
18061
  }
18062
+ function finiteValuesForDependency(key, domain) {
18063
+ if (!domain) {
18064
+ throw new Error(
18065
+ `Interaction input '${key}' is declared as a dependency before it has a projected domain.`
18066
+ );
18067
+ }
18068
+ if (domain.type === "target") {
18069
+ if (!domain.eligibleTargets) {
18070
+ throw new Error(
18071
+ `Interaction input '${key}' cannot be used as a dependency because its target domain is not finite.`
18072
+ );
18073
+ }
18074
+ return [...domain.eligibleTargets];
18075
+ }
18076
+ if (domain.type === "choice") {
18077
+ return domain.choices.flatMap(
18078
+ (choice) => choice.value === null ? [] : [choice.value]
18079
+ );
18080
+ }
18081
+ throw new Error(
18082
+ `Interaction input '${key}' cannot be used as a dependency. V1 supports finite target and choice dependencies only.`
18083
+ );
18084
+ }
18085
+ function cartesianDependencyTuples(dependencies, domainsByKey) {
18086
+ return dependencies.reduce(
18087
+ (tuples, key) => {
18088
+ const values = finiteValuesForDependency(key, domainsByKey[key]);
18089
+ return tuples.flatMap(
18090
+ (tuple) => values.map((value) => ({ ...tuple, [key]: value }))
18091
+ );
18092
+ },
18093
+ [{}]
18094
+ );
18095
+ }
18096
+ function withoutDependentProjection(domain) {
18097
+ const {
18098
+ dependsOn: _dependsOn,
18099
+ dependentCases: _dependentCases,
18100
+ ...rest
18101
+ } = domain;
18102
+ return rest;
18103
+ }
17599
18104
  function unsupportedDefaultInputError(key, collector) {
17600
18105
  return new Error(
17601
18106
  `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.`
@@ -17644,19 +18149,74 @@ function collectInputDomains(interaction, domainState, playerId, eligibleTargets
17644
18149
  const derived = () => derivedLazy ??= createDerivedResolver(domainState, { q: queries() });
17645
18150
  const result = {};
17646
18151
  for (const [key, collector] of Object.entries(collectors)) {
17647
- if (collector.kind === "rng" || collector.kind === "prompt") {
18152
+ if (collector.kind === "rng") {
18153
+ continue;
18154
+ }
18155
+ if (collector.kind === "prompt") {
18156
+ const optionFactory = collector.meta?.options;
18157
+ if (!optionFactory) continue;
18158
+ result[key] = {
18159
+ type: "choice",
18160
+ choices: optionFactory(domainState, playerId, queries()).map(
18161
+ (option) => ({
18162
+ value: String(option.id),
18163
+ label: option.label ?? String(option.id),
18164
+ ...(() => {
18165
+ const issue = collector.validateTarget?.(
18166
+ domainState,
18167
+ playerId,
18168
+ queries(),
18169
+ String(option.id)
18170
+ );
18171
+ return issue ? {
18172
+ disabled: true,
18173
+ disabledReason: issue.message ?? issue.errorCode
18174
+ } : {};
18175
+ })()
18176
+ })
18177
+ )
18178
+ };
17648
18179
  continue;
17649
18180
  }
17650
18181
  if (collector.domain) {
17651
- result[key] = withSelection(
18182
+ const dependencies = collector.dependsOn ?? [];
18183
+ const baseDomain = withSelection(
17652
18184
  collector.domain(
17653
18185
  domainState,
17654
18186
  playerId,
17655
18187
  queries(),
17656
- derived()
18188
+ derived(),
18189
+ {}
17657
18190
  ),
17658
18191
  collector
17659
18192
  );
18193
+ if (dependencies.length === 0) {
18194
+ result[key] = baseDomain;
18195
+ continue;
18196
+ }
18197
+ const dependentCases = cartesianDependencyTuples(
18198
+ dependencies,
18199
+ result
18200
+ ).map((values) => ({
18201
+ when: values,
18202
+ domain: withoutDependentProjection(
18203
+ withSelection(
18204
+ collector.domain?.(
18205
+ domainState,
18206
+ playerId,
18207
+ queries(),
18208
+ derived(),
18209
+ values
18210
+ ),
18211
+ collector
18212
+ )
18213
+ )
18214
+ }));
18215
+ result[key] = {
18216
+ ...baseDomain,
18217
+ dependsOn: dependencies,
18218
+ dependentCases
18219
+ };
17660
18220
  continue;
17661
18221
  }
17662
18222
  const targets = eligibleTargets[key];
@@ -17678,7 +18238,17 @@ function collectInputDomains(interaction, domainState, playerId, eligibleTargets
17678
18238
  }
17679
18239
  function collectInteractionInputs(interaction, domainState, playerId, options = {}) {
17680
18240
  const collectors = interactionInputsOf(interaction);
17681
- const eligibleTargets = options.includeEligibleTargets === false ? {} : collectEligibleTargets(interaction, domainState, playerId, options);
18241
+ const dependencyKeys = new Set(
18242
+ Object.values(collectors).flatMap((collector) => [
18243
+ ...collector.dependsOn ?? []
18244
+ ])
18245
+ );
18246
+ const collectedEligibleTargets = options.includeEligibleTargets === false && dependencyKeys.size === 0 ? {} : collectEligibleTargets(interaction, domainState, playerId, options);
18247
+ const eligibleTargets = options.includeEligibleTargets === false ? Object.fromEntries(
18248
+ Object.entries(collectedEligibleTargets).filter(
18249
+ ([key]) => dependencyKeys.has(key)
18250
+ )
18251
+ ) : collectedEligibleTargets;
17682
18252
  const domainsByKey = collectInputDomains(
17683
18253
  interaction,
17684
18254
  domainState,
@@ -17693,10 +18263,13 @@ function collectInteractionInputs(interaction, domainState, playerId, options =
17693
18263
  let derivedLazy = options.derived ?? null;
17694
18264
  const derived = () => derivedLazy ??= createDerivedResolver(domainState, { q: queries() });
17695
18265
  return Object.entries(collectors).flatMap(([key, collector]) => {
17696
- if (collector.kind === "rng" || collector.kind === "prompt") {
18266
+ if (collector.kind === "rng") {
17697
18267
  return [];
17698
18268
  }
17699
18269
  const domain = domainsByKey[key];
18270
+ if (!domain && collector.kind === "prompt") {
18271
+ return [];
18272
+ }
17700
18273
  if (!domain) {
17701
18274
  throw unsupportedDefaultInputError(key, collector);
17702
18275
  }
@@ -17743,7 +18316,7 @@ function collectCardZoneIds(interaction) {
17743
18316
  function collectPromptOptions(interaction, domainState, playerId, queries) {
17744
18317
  for (const collector of Object.values(interaction.inputs)) {
17745
18318
  if (collector.kind !== "prompt") continue;
17746
- const factory = collector.meta?.eligibleOptions;
18319
+ const factory = collector.meta?.options;
17747
18320
  if (!factory) continue;
17748
18321
  return factory(domainState, playerId, queries).map((option) => ({
17749
18322
  id: String(option.id),
@@ -17769,7 +18342,12 @@ function parseInteractionParams(interaction, rawParams, options = {}) {
17769
18342
  const issues = [];
17770
18343
  for (const [key, collector] of Object.entries(collectors)) {
17771
18344
  if (collector.kind === "rng" && options.skipRng) continue;
17772
- const rawValue = record[key] === void 0 && "defaultValue" in collector ? collector.defaultValue : record[key];
18345
+ const rawValueBase = record[key] === void 0 && "defaultValue" in collector ? collector.defaultValue : record[key];
18346
+ const rawValue = collector.kind === "board-space" && collector.meta?.valueKind === "player-board-space" && typeof rawValueBase === "string" && options.playerId ? {
18347
+ boardId: collector.meta.boardId,
18348
+ playerId: options.playerId,
18349
+ spaceId: rawValueBase
18350
+ } : rawValueBase;
17773
18351
  const result = collector.schema.safeParse(rawValue);
17774
18352
  if (!result.success) {
17775
18353
  for (const issue of result.error.issues) {
@@ -17831,7 +18409,7 @@ function validateCollectorTargets(interaction, domainState, playerId, params) {
17831
18409
  domainState,
17832
18410
  playerId,
17833
18411
  queries(),
17834
- String(value)
18412
+ value
17835
18413
  );
17836
18414
  if (issue) {
17837
18415
  return makeValidationError(issue.errorCode, issue.message);
@@ -18043,11 +18621,14 @@ function deriveCommitPolicy(inputs, explicit) {
18043
18621
  if (hasManyCollector) {
18044
18622
  return { mode: "manual" };
18045
18623
  }
18624
+ if (collectors.some(isDefaultRenderableFormCollector)) {
18625
+ return { mode: "manual" };
18626
+ }
18046
18627
  if (collectors.length === 0 || !collectors.some(isTargetCollector2)) {
18047
18628
  return { mode: "manual" };
18048
18629
  }
18049
18630
  return collectors.every(
18050
- (collector) => isTargetCollector2(collector) || isDefaultRenderableFormCollector(collector) || collector.kind === "rng"
18631
+ (collector) => isTargetCollector2(collector) || collector.kind === "rng"
18051
18632
  ) ? { mode: "autoWhenReady" } : { mode: "manual" };
18052
18633
  }
18053
18634
  function projectInteractionMetadata(interaction) {
@@ -18063,7 +18644,7 @@ function enrichResourceInputPresentation(inputs, manifest) {
18063
18644
  }
18064
18645
  const resources = presentationById;
18065
18646
  const enrichChoice = (choice) => {
18066
- const presentation = resources[choice.value];
18647
+ const presentation = choice.value === null ? void 0 : resources[choice.value];
18067
18648
  return {
18068
18649
  ...choice,
18069
18650
  label: typeof presentation?.label === "string" && (!choice.label || choice.label === choice.value) ? presentation.label : choice.label || (typeof presentation?.label === "string" ? presentation.label : ""),
@@ -18071,7 +18652,16 @@ function enrichResourceInputPresentation(inputs, manifest) {
18071
18652
  };
18072
18653
  };
18073
18654
  return inputs.map((input) => {
18074
- if (input.domain.type === "choice" || input.domain.type === "choiceList") {
18655
+ if (input.domain.type === "choice") {
18656
+ return {
18657
+ ...input,
18658
+ domain: {
18659
+ ...input.domain,
18660
+ choices: input.domain.choices.map(enrichChoice)
18661
+ }
18662
+ };
18663
+ }
18664
+ if (input.domain.type === "choiceList") {
18075
18665
  return {
18076
18666
  ...input,
18077
18667
  domain: {
@@ -18191,7 +18781,10 @@ function createInteractionDecisionResolver(scope, stages, authorization) {
18191
18781
  }
18192
18782
  const trustedInteractionId = interactionId;
18193
18783
  const parseForSubmit = mode === "submit";
18194
- const parsed = parseForSubmit ? parseInteractionParams(interaction, params, { skipRng: true }) : {
18784
+ const parsed = parseForSubmit ? parseInteractionParams(interaction, params, {
18785
+ skipRng: true,
18786
+ playerId
18787
+ }) : {
18195
18788
  ok: true,
18196
18789
  params: prepareInteractionProjectionParams(interaction, params)
18197
18790
  };
@@ -18451,10 +19044,7 @@ function createStageResolver(scope) {
18451
19044
  return allowlist;
18452
19045
  }
18453
19046
  function isInteractionAllowedInStep(state, interaction, projection) {
18454
- const allowedSteps = [
18455
- ...interaction.step !== void 0 ? [interaction.step] : [],
18456
- ...interaction.steps ?? []
18457
- ];
19047
+ const allowedSteps = interaction.__steps ?? [];
18458
19048
  if (allowedSteps.length === 0) {
18459
19049
  return true;
18460
19050
  }
@@ -18583,16 +19173,15 @@ function resolveContainerRef(table, ref) {
18583
19173
  throw new Error(`Unknown board '${ref.boardId}'.`);
18584
19174
  }
18585
19175
  const space2 = board2?.spaces[ref.spaceId];
18586
- if (!space2?.zoneId) {
19176
+ if (!space2) {
18587
19177
  throw new Error(
18588
- `Board space '${ref.spaceId}' on board '${ref.boardId}' has no container zone.`
19178
+ `Unknown board space '${ref.spaceId}' on board '${ref.boardId}'.`
18589
19179
  );
18590
19180
  }
18591
19181
  return {
18592
19182
  kind: "space",
18593
19183
  boardId: board2.id,
18594
- spaceId: ref.spaceId,
18595
- zoneId: space2.zoneId
19184
+ spaceId: ref.spaceId
18596
19185
  };
18597
19186
  }
18598
19187
  const board = table.boards.byId[resolveRuntimeBoardId(table, ref.boardId, ref.playerId)];
@@ -18602,16 +19191,15 @@ function resolveContainerRef(table, ref) {
18602
19191
  );
18603
19192
  }
18604
19193
  const space = board?.spaces[ref.spaceId];
18605
- if (!space?.zoneId) {
19194
+ if (!space) {
18606
19195
  throw new Error(
18607
- `Board space '${ref.spaceId}' on board '${ref.boardId}' for '${ref.playerId}' has no container zone.`
19196
+ `Unknown board space '${ref.spaceId}' on board '${ref.boardId}' for '${ref.playerId}'.`
18608
19197
  );
18609
19198
  }
18610
19199
  return {
18611
19200
  kind: "space",
18612
19201
  boardId: board.id,
18613
- spaceId: ref.spaceId,
18614
- zoneId: space.zoneId
19202
+ spaceId: ref.spaceId
18615
19203
  };
18616
19204
  }
18617
19205
  function readContainerComponents(table, ref) {
@@ -18922,7 +19510,11 @@ function createLifecycleRunner(scope, interactions) {
18922
19510
  }) : safeParseOrThrow(phase.state, {}, `phase:${phaseName}:initialState`);
18923
19511
  return {
18924
19512
  ...state,
18925
- phase: safeParseOrThrow(phase.state, phaseState, `phase:${phaseName}`),
19513
+ phase: safeParseOrThrow(
19514
+ phase.state,
19515
+ phaseState,
19516
+ `phase:${phaseName}`
19517
+ ),
18926
19518
  flow: {
18927
19519
  ...state.flow,
18928
19520
  currentPhase: phaseName
@@ -18940,12 +19532,17 @@ function createLifecycleRunner(scope, interactions) {
18940
19532
  let nextState = workingState;
18941
19533
  const instructions = [];
18942
19534
  if (phase.enter) {
19535
+ const random = createMutableRandomHelpers(workingState.runtime.rng);
18943
19536
  const entered = normalizeResult(
18944
19537
  phase.enter(
18945
- scope.buildRuntimeArgs(workingState, {
18946
- event,
18947
- state: scope.toDomainState(workingState)
18948
- })
19538
+ scope.buildRuntimeArgs(
19539
+ workingState,
19540
+ {
19541
+ event,
19542
+ state: scope.toDomainState(workingState)
19543
+ },
19544
+ { random: random.random }
19545
+ )
18949
19546
  ),
18950
19547
  scope.toDomainState(workingState)
18951
19548
  );
@@ -18956,18 +19553,23 @@ function createLifecycleRunner(scope, interactions) {
18956
19553
  }
18957
19554
  nextState = {
18958
19555
  ...entered.state,
18959
- runtime: workingState.runtime
19556
+ runtime: { ...workingState.runtime, rng: random.currentRng() }
18960
19557
  };
18961
19558
  if (entered.instructions) instructions.push(...entered.instructions);
18962
19559
  }
18963
19560
  const activeStage = interactions.resolveActiveStage(nextState, phaseName);
18964
19561
  if (activeStage?.stage.onEnter) {
19562
+ const random = createMutableRandomHelpers(nextState.runtime.rng);
18965
19563
  const stageEntered = normalizeResult(
18966
19564
  activeStage.stage.onEnter(
18967
- scope.buildRuntimeArgs(nextState, {
18968
- event,
18969
- state: scope.toDomainState(nextState)
18970
- })
19565
+ scope.buildRuntimeArgs(
19566
+ nextState,
19567
+ {
19568
+ event,
19569
+ state: scope.toDomainState(nextState)
19570
+ },
19571
+ { random: random.random }
19572
+ )
18971
19573
  ),
18972
19574
  scope.toDomainState(nextState)
18973
19575
  );
@@ -18978,7 +19580,7 @@ function createLifecycleRunner(scope, interactions) {
18978
19580
  }
18979
19581
  nextState = {
18980
19582
  ...stageEntered.state,
18981
- runtime: nextState.runtime
19583
+ runtime: { ...nextState.runtime, rng: random.currentRng() }
18982
19584
  };
18983
19585
  if (stageEntered.instructions) {
18984
19586
  instructions.push(...stageEntered.instructions);
@@ -20031,6 +20633,11 @@ function toWireDispatchResult(result, serializeState) {
20031
20633
  function createReducerBundle(definition) {
20032
20634
  const trustedBundle = createTrustedReducerBundle(definition);
20033
20635
  const codec = createIngressRuntimeCodec(definition);
20636
+ function parseTrustedState(state) {
20637
+ return codec.parseState(
20638
+ state
20639
+ );
20640
+ }
20034
20641
  function parseRuntimePlayerId(playerId) {
20035
20642
  if (typeof playerId !== "string") {
20036
20643
  throw new Error("Expected a string playerId.");
@@ -20063,7 +20670,7 @@ function createReducerBundle(definition) {
20063
20670
  );
20064
20671
  },
20065
20672
  async initializePhase({ state, to }) {
20066
- const decodedState = codec.parseState(state);
20673
+ const decodedState = parseTrustedState(state);
20067
20674
  return codec.serializeState(
20068
20675
  await trustedBundle.initializePhase({
20069
20676
  state: decodedState,
@@ -20075,7 +20682,7 @@ function createReducerBundle(definition) {
20075
20682
  const validatedWire = codec.parseInput(input);
20076
20683
  const routed = routeInteraction(validatedWire);
20077
20684
  return trustedBundle.validateInput({
20078
- state: codec.parseState(state),
20685
+ state: parseTrustedState(state),
20079
20686
  input: routed
20080
20687
  });
20081
20688
  },
@@ -20086,7 +20693,7 @@ function createReducerBundle(definition) {
20086
20693
  const validatedWire = codec.parseInput(input);
20087
20694
  const routed = routeInteraction(validatedWire);
20088
20695
  const result = await trustedBundle.reduce({
20089
- state: codec.parseState(state),
20696
+ state: parseTrustedState(state),
20090
20697
  input: routed
20091
20698
  });
20092
20699
  return toWireReduceResult(
@@ -20101,7 +20708,7 @@ function createReducerBundle(definition) {
20101
20708
  const validatedWire = codec.parseInput(input);
20102
20709
  const routed = routeInteraction(validatedWire);
20103
20710
  const result = await trustedBundle.dispatch({
20104
- state: codec.parseState(state),
20711
+ state: parseTrustedState(state),
20105
20712
  input: routed
20106
20713
  });
20107
20714
  return toWireDispatchResult(
@@ -20128,7 +20735,7 @@ function createReducerBundle(definition) {
20128
20735
  playerIds,
20129
20736
  viewId = "player"
20130
20737
  }) {
20131
- const parsedState = codec.parseState(state);
20738
+ const parsedState = parseTrustedState(state);
20132
20739
  const parsedPlayerIds = playerIds.map((pid) => codec.parsePlayerId(pid));
20133
20740
  return trustedBundle.projectSeatsDynamic({
20134
20741
  state: parsedState,
@@ -20137,9 +20744,7 @@ function createReducerBundle(definition) {
20137
20744
  });
20138
20745
  },
20139
20746
  projectSeatViewDynamic({ state, playerId, viewId = "player" }) {
20140
- const parsedState = codec.parseState(
20141
- state
20142
- );
20747
+ const parsedState = parseTrustedState(state);
20143
20748
  return trustedBundle.projectSeatViewDynamic({
20144
20749
  state: parsedState,
20145
20750
  playerId: parseRuntimePlayerId(playerId),
@@ -20168,7 +20773,7 @@ function createReducerBundle(definition) {
20168
20773
  });
20169
20774
  },
20170
20775
  hydrate({ state: snapshot }) {
20171
- state = codec.parseState(snapshot);
20776
+ state = parseTrustedState(snapshot);
20172
20777
  },
20173
20778
  async dispatch({ input }) {
20174
20779
  const validatedWire = codec.parseInput(
@@ -26225,4 +26830,4 @@ export {
26225
26830
  test_default,
26226
26831
  runDreamboardCli
26227
26832
  };
26228
- //# sourceMappingURL=chunk-WDTE6OFH.js.map
26833
+ //# sourceMappingURL=chunk-ZLYS5DGK.js.map