@bct-app/game-engine 0.1.20 → 0.1.21

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/index.d.mts CHANGED
@@ -133,9 +133,6 @@ type TDslPlayer = TPlayer & {
133
133
  characterKind: string | undefined;
134
134
  reminderMarks: string[];
135
135
  effectiveAlive: boolean;
136
- diedThisTurn: boolean;
137
- wasExecuted: boolean;
138
- wasExecutedToday: boolean;
139
136
  };
140
137
  type TDslNomination = {
141
138
  nominator: number;
@@ -161,6 +158,7 @@ type TDslContext = {
161
158
  };
162
159
  currentTimeline: {
163
160
  turn: number;
161
+ previousTurn: number;
164
162
  phase: string;
165
163
  time: TTimeline['time'] | undefined;
166
164
  isFirstOfPhase: boolean;
package/dist/index.d.ts CHANGED
@@ -133,9 +133,6 @@ type TDslPlayer = TPlayer & {
133
133
  characterKind: string | undefined;
134
134
  reminderMarks: string[];
135
135
  effectiveAlive: boolean;
136
- diedThisTurn: boolean;
137
- wasExecuted: boolean;
138
- wasExecutedToday: boolean;
139
136
  };
140
137
  type TDslNomination = {
141
138
  nominator: number;
@@ -161,6 +158,7 @@ type TDslContext = {
161
158
  };
162
159
  currentTimeline: {
163
160
  turn: number;
161
+ previousTurn: number;
164
162
  phase: string;
165
163
  time: TTimeline['time'] | undefined;
166
164
  isFirstOfPhase: boolean;
package/dist/index.js CHANGED
@@ -521,7 +521,8 @@ var applyStatusChange = createEffectHandler("STATUS_CHANGE", ({
521
521
  makePlayersEffect,
522
522
  operationTurn,
523
523
  abilityMap,
524
- operation
524
+ operation,
525
+ operationTime
525
526
  }) => {
526
527
  const maybeStatus = getSourceValue(effect.source, payloads);
527
528
  if (maybeStatus === "DEAD") {
@@ -531,6 +532,7 @@ var applyStatusChange = createEffectHandler("STATUS_CHANGE", ({
531
532
  player.isDead = true;
532
533
  player.deathCause = cause;
533
534
  player.deathTurn = operationTurn;
535
+ player.deathTime = operationTime;
534
536
  });
535
537
  return;
536
538
  }
@@ -539,6 +541,7 @@ var applyStatusChange = createEffectHandler("STATUS_CHANGE", ({
539
541
  player.isDead = false;
540
542
  delete player.deathCause;
541
543
  delete player.deathTurn;
544
+ delete player.deathTime;
542
545
  });
543
546
  return;
544
547
  }
@@ -561,18 +564,14 @@ var effectHandlers = {
561
564
  };
562
565
 
563
566
  // src/dsl/context.ts
564
- var decoratePlayer = (player, characterMap, currentTurn) => {
567
+ var decoratePlayer = (player, characterMap) => {
565
568
  const isDead = Boolean(player.isDead);
566
569
  const retainsBypass = isDead && (player.retainsAbility === "ALIVENESS" || player.retainsAbility === "ALL");
567
- const wasExecuted = isDead && player.deathCause === "EXECUTION";
568
570
  return {
569
571
  ...player,
570
572
  characterKind: characterMap.get(player.characterId)?.kind,
571
573
  reminderMarks: (player.reminders ?? []).map((r) => r.mark),
572
- effectiveAlive: !isDead || retainsBypass,
573
- diedThisTurn: isDead && typeof player.deathTurn === "number" && player.deathTurn === currentTurn,
574
- wasExecuted,
575
- wasExecutedToday: wasExecuted && player.deathTurn === currentTurn
574
+ effectiveAlive: !isDead || retainsBypass
576
575
  };
577
576
  };
578
577
  var isExecutionTimeline = (tl) => {
@@ -580,7 +579,7 @@ var isExecutionTimeline = (tl) => {
580
579
  return (tl.operations ?? []).some((op) => op.kind === "execution");
581
580
  };
582
581
  var buildDslContextFromDerived = (derived, payload = []) => {
583
- const players = derived.players.map((p) => decoratePlayer(p, derived.characterMap, derived.currentTurn));
582
+ const players = derived.players.map((p) => decoratePlayer(p, derived.characterMap));
584
583
  const effector = players.find((p) => p.seat === derived.effectorSeat);
585
584
  const aliveCount = players.filter((p) => !p.isDead).length;
586
585
  const deadCount = players.length - aliveCount;
@@ -608,6 +607,7 @@ var buildDslContextFromDerived = (derived, payload = []) => {
608
607
  },
609
608
  currentTimeline: {
610
609
  turn: derived.currentTurn,
610
+ previousTurn: derived.currentTurn - 1,
611
611
  phase: derived.currentPhase,
612
612
  time: derived.currentPhase === "NIGHT" ? "night" : derived.currentPhase === "DAY" ? "day" : void 0,
613
613
  isFirstOfPhase: derived.isFirstOfPhase,
@@ -637,8 +637,8 @@ var buildDslContextFromLifetime = ({
637
637
  const currentTime = nowTl?.time;
638
638
  const currentPhase = currentTime === "night" ? "NIGHT" : currentTime === "day" ? "DAY" : "NIGHT";
639
639
  const playersRaw = snapshotSeatMap ? [...snapshotSeatMap.values()] : [];
640
- const players = playersRaw.map((p) => decoratePlayer(p, characterMap, currentTurn));
641
- const effectorDecorated = effector ? players.find((p) => p.seat === effector.seat) ?? decoratePlayer(effector, characterMap, currentTurn) : void 0;
640
+ const players = playersRaw.map((p) => decoratePlayer(p, characterMap));
641
+ const effectorDecorated = effector ? players.find((p) => p.seat === effector.seat) ?? decoratePlayer(effector, characterMap) : void 0;
642
642
  const todayOps = timelines.filter((tl) => tl.turn === currentTurn && tl.time === "day").flatMap((tl) => tl.operations ?? []);
643
643
  const tonightOps = timelines.filter((tl) => tl.turn === currentTurn && tl.time === "night").flatMap((tl) => tl.operations ?? []);
644
644
  const yesterdayDayOps = timelines.filter((tl) => tl.turn === currentTurn - 1 && tl.time === "day").flatMap((tl) => tl.operations ?? []);
@@ -680,6 +680,7 @@ var buildDslContextFromLifetime = ({
680
680
  },
681
681
  currentTimeline: {
682
682
  turn: currentTurn,
683
+ previousTurn: currentTurn - 1,
683
684
  phase: currentPhase,
684
685
  time: currentTime,
685
686
  isFirstOfPhase: false,
@@ -868,13 +869,11 @@ var PLAYER_FIELDS = [
868
869
  { name: "alignment", type: "string", label: "\u9635\u8425", description: "GOOD / EVIL" },
869
870
  { name: "isDead", type: "boolean", label: "\u662F\u5426\u6B7B\u4EA1" },
870
871
  { name: "effectiveAlive", type: "boolean", label: "\u6709\u6548\u5B58\u6D3B", description: "\u8003\u8651 retainsAbility\uFF08ALIVENESS/ALL\uFF09\u540E\u662F\u5426\u6309\u5B58\u6D3B\u5904\u7406" },
871
- { name: "diedThisTurn", type: "boolean", label: "\u672C\u56DE\u5408\u6B7B\u4EA1" },
872
- { name: "wasExecuted", type: "boolean", label: "\u66FE\u88AB\u5904\u51B3" },
873
- { name: "wasExecutedToday", type: "boolean", label: "\u4ECA\u65E5\u88AB\u5904\u51B3" },
874
872
  { name: "characterId", type: "string", label: "\u89D2\u8272 ID" },
875
873
  { name: "characterKind", type: "string", label: "\u89D2\u8272\u7C7B\u578B", description: "Townsfolk / Outsiders / Minions / Demons" },
876
874
  { name: "deathCause", type: "string", label: "\u6B7B\u4EA1\u539F\u56E0", description: "EXECUTION / DEMON / ABILITY / STORYTELLER / OTHER" },
877
875
  { name: "deathTurn", type: "number", label: "\u6B7B\u4EA1\u56DE\u5408" },
876
+ { name: "deathTime", type: "string", label: "\u6B7B\u4EA1\u65F6\u6BB5", description: "day / night" },
878
877
  { name: "abilities", type: "string[]", label: "\u80FD\u529B ID \u5217\u8868" },
879
878
  { name: "reminderMarks", type: "string[]", label: "\u63D0\u793A\u7269 mark \u5217\u8868" },
880
879
  { name: "hasUsedDeadVote", type: "boolean", label: "\u662F\u5426\u4F7F\u7528\u8FC7\u6B7B\u4EA1\u6295\u7968" },
@@ -893,6 +892,7 @@ var NOMINATION_FIELDS = [
893
892
  ];
894
893
  var CURRENT_TIMELINE_FIELDS = [
895
894
  { name: "turn", type: "number", label: "\u5F53\u524D\u56DE\u5408" },
895
+ { name: "previousTurn", type: "number", label: "\u4E0A\u4E00\u56DE\u5408", description: "= turn - 1\uFF0C\u9996\u56DE\u5408\u4E3A -1" },
896
896
  { name: "phase", type: "string", label: "\u5F53\u524D\u9636\u6BB5", description: "NIGHT / DAY / DUSK / DAWN" },
897
897
  { name: "time", type: "string", label: "\u5F53\u524D\u65F6\u6BB5", description: "night / day" },
898
898
  { name: "isFirstOfPhase", type: "boolean", label: "\u662F\u5426\u672C\u9636\u6BB5\u9996\u6B21" },
@@ -1708,6 +1708,7 @@ var applyOperationToPlayers = ({
1708
1708
  nowTimelineIndex,
1709
1709
  operationInTimelineIdx: record.operationInTimelineIdx,
1710
1710
  operationTurn: timelines[record.operationInTimelineIdx]?.turn ?? 0,
1711
+ operationTime: timelines[record.operationInTimelineIdx]?.time ?? "night",
1711
1712
  makePlayersEffect
1712
1713
  };
1713
1714
  handler(context);
package/dist/index.mjs CHANGED
@@ -465,7 +465,8 @@ var applyStatusChange = createEffectHandler("STATUS_CHANGE", ({
465
465
  makePlayersEffect,
466
466
  operationTurn,
467
467
  abilityMap,
468
- operation
468
+ operation,
469
+ operationTime
469
470
  }) => {
470
471
  const maybeStatus = getSourceValue(effect.source, payloads);
471
472
  if (maybeStatus === "DEAD") {
@@ -475,6 +476,7 @@ var applyStatusChange = createEffectHandler("STATUS_CHANGE", ({
475
476
  player.isDead = true;
476
477
  player.deathCause = cause;
477
478
  player.deathTurn = operationTurn;
479
+ player.deathTime = operationTime;
478
480
  });
479
481
  return;
480
482
  }
@@ -483,6 +485,7 @@ var applyStatusChange = createEffectHandler("STATUS_CHANGE", ({
483
485
  player.isDead = false;
484
486
  delete player.deathCause;
485
487
  delete player.deathTurn;
488
+ delete player.deathTime;
486
489
  });
487
490
  return;
488
491
  }
@@ -505,18 +508,14 @@ var effectHandlers = {
505
508
  };
506
509
 
507
510
  // src/dsl/context.ts
508
- var decoratePlayer = (player, characterMap, currentTurn) => {
511
+ var decoratePlayer = (player, characterMap) => {
509
512
  const isDead = Boolean(player.isDead);
510
513
  const retainsBypass = isDead && (player.retainsAbility === "ALIVENESS" || player.retainsAbility === "ALL");
511
- const wasExecuted = isDead && player.deathCause === "EXECUTION";
512
514
  return {
513
515
  ...player,
514
516
  characterKind: characterMap.get(player.characterId)?.kind,
515
517
  reminderMarks: (player.reminders ?? []).map((r) => r.mark),
516
- effectiveAlive: !isDead || retainsBypass,
517
- diedThisTurn: isDead && typeof player.deathTurn === "number" && player.deathTurn === currentTurn,
518
- wasExecuted,
519
- wasExecutedToday: wasExecuted && player.deathTurn === currentTurn
518
+ effectiveAlive: !isDead || retainsBypass
520
519
  };
521
520
  };
522
521
  var isExecutionTimeline = (tl) => {
@@ -524,7 +523,7 @@ var isExecutionTimeline = (tl) => {
524
523
  return (tl.operations ?? []).some((op) => op.kind === "execution");
525
524
  };
526
525
  var buildDslContextFromDerived = (derived, payload = []) => {
527
- const players = derived.players.map((p) => decoratePlayer(p, derived.characterMap, derived.currentTurn));
526
+ const players = derived.players.map((p) => decoratePlayer(p, derived.characterMap));
528
527
  const effector = players.find((p) => p.seat === derived.effectorSeat);
529
528
  const aliveCount = players.filter((p) => !p.isDead).length;
530
529
  const deadCount = players.length - aliveCount;
@@ -552,6 +551,7 @@ var buildDslContextFromDerived = (derived, payload = []) => {
552
551
  },
553
552
  currentTimeline: {
554
553
  turn: derived.currentTurn,
554
+ previousTurn: derived.currentTurn - 1,
555
555
  phase: derived.currentPhase,
556
556
  time: derived.currentPhase === "NIGHT" ? "night" : derived.currentPhase === "DAY" ? "day" : void 0,
557
557
  isFirstOfPhase: derived.isFirstOfPhase,
@@ -581,8 +581,8 @@ var buildDslContextFromLifetime = ({
581
581
  const currentTime = nowTl?.time;
582
582
  const currentPhase = currentTime === "night" ? "NIGHT" : currentTime === "day" ? "DAY" : "NIGHT";
583
583
  const playersRaw = snapshotSeatMap ? [...snapshotSeatMap.values()] : [];
584
- const players = playersRaw.map((p) => decoratePlayer(p, characterMap, currentTurn));
585
- const effectorDecorated = effector ? players.find((p) => p.seat === effector.seat) ?? decoratePlayer(effector, characterMap, currentTurn) : void 0;
584
+ const players = playersRaw.map((p) => decoratePlayer(p, characterMap));
585
+ const effectorDecorated = effector ? players.find((p) => p.seat === effector.seat) ?? decoratePlayer(effector, characterMap) : void 0;
586
586
  const todayOps = timelines.filter((tl) => tl.turn === currentTurn && tl.time === "day").flatMap((tl) => tl.operations ?? []);
587
587
  const tonightOps = timelines.filter((tl) => tl.turn === currentTurn && tl.time === "night").flatMap((tl) => tl.operations ?? []);
588
588
  const yesterdayDayOps = timelines.filter((tl) => tl.turn === currentTurn - 1 && tl.time === "day").flatMap((tl) => tl.operations ?? []);
@@ -624,6 +624,7 @@ var buildDslContextFromLifetime = ({
624
624
  },
625
625
  currentTimeline: {
626
626
  turn: currentTurn,
627
+ previousTurn: currentTurn - 1,
627
628
  phase: currentPhase,
628
629
  time: currentTime,
629
630
  isFirstOfPhase: false,
@@ -812,13 +813,11 @@ var PLAYER_FIELDS = [
812
813
  { name: "alignment", type: "string", label: "\u9635\u8425", description: "GOOD / EVIL" },
813
814
  { name: "isDead", type: "boolean", label: "\u662F\u5426\u6B7B\u4EA1" },
814
815
  { name: "effectiveAlive", type: "boolean", label: "\u6709\u6548\u5B58\u6D3B", description: "\u8003\u8651 retainsAbility\uFF08ALIVENESS/ALL\uFF09\u540E\u662F\u5426\u6309\u5B58\u6D3B\u5904\u7406" },
815
- { name: "diedThisTurn", type: "boolean", label: "\u672C\u56DE\u5408\u6B7B\u4EA1" },
816
- { name: "wasExecuted", type: "boolean", label: "\u66FE\u88AB\u5904\u51B3" },
817
- { name: "wasExecutedToday", type: "boolean", label: "\u4ECA\u65E5\u88AB\u5904\u51B3" },
818
816
  { name: "characterId", type: "string", label: "\u89D2\u8272 ID" },
819
817
  { name: "characterKind", type: "string", label: "\u89D2\u8272\u7C7B\u578B", description: "Townsfolk / Outsiders / Minions / Demons" },
820
818
  { name: "deathCause", type: "string", label: "\u6B7B\u4EA1\u539F\u56E0", description: "EXECUTION / DEMON / ABILITY / STORYTELLER / OTHER" },
821
819
  { name: "deathTurn", type: "number", label: "\u6B7B\u4EA1\u56DE\u5408" },
820
+ { name: "deathTime", type: "string", label: "\u6B7B\u4EA1\u65F6\u6BB5", description: "day / night" },
822
821
  { name: "abilities", type: "string[]", label: "\u80FD\u529B ID \u5217\u8868" },
823
822
  { name: "reminderMarks", type: "string[]", label: "\u63D0\u793A\u7269 mark \u5217\u8868" },
824
823
  { name: "hasUsedDeadVote", type: "boolean", label: "\u662F\u5426\u4F7F\u7528\u8FC7\u6B7B\u4EA1\u6295\u7968" },
@@ -837,6 +836,7 @@ var NOMINATION_FIELDS = [
837
836
  ];
838
837
  var CURRENT_TIMELINE_FIELDS = [
839
838
  { name: "turn", type: "number", label: "\u5F53\u524D\u56DE\u5408" },
839
+ { name: "previousTurn", type: "number", label: "\u4E0A\u4E00\u56DE\u5408", description: "= turn - 1\uFF0C\u9996\u56DE\u5408\u4E3A -1" },
840
840
  { name: "phase", type: "string", label: "\u5F53\u524D\u9636\u6BB5", description: "NIGHT / DAY / DUSK / DAWN" },
841
841
  { name: "time", type: "string", label: "\u5F53\u524D\u65F6\u6BB5", description: "night / day" },
842
842
  { name: "isFirstOfPhase", type: "boolean", label: "\u662F\u5426\u672C\u9636\u6BB5\u9996\u6B21" },
@@ -1652,6 +1652,7 @@ var applyOperationToPlayers = ({
1652
1652
  nowTimelineIndex,
1653
1653
  operationInTimelineIdx: record.operationInTimelineIdx,
1654
1654
  operationTurn: timelines[record.operationInTimelineIdx]?.turn ?? 0,
1655
+ operationTime: timelines[record.operationInTimelineIdx]?.time ?? "night",
1655
1656
  makePlayersEffect
1656
1657
  };
1657
1658
  handler(context);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bct-app/game-engine",
3
- "version": "0.1.20",
3
+ "version": "0.1.21",
4
4
  "description": "Game engine utilities for BCT",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -30,7 +30,7 @@
30
30
  "access": "public"
31
31
  },
32
32
  "dependencies": {
33
- "@bct-app/game-model": "0.1.13"
33
+ "@bct-app/game-model": "0.1.14"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@vitest/ui": "^4.1.3",