@bct-app/game-engine 0.1.9 → 0.1.11

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.js CHANGED
@@ -471,6 +471,28 @@ var applyReminderRemove = createEffectHandler("REMINDER_REMOVE", ({ effect, payl
471
471
  });
472
472
  });
473
473
 
474
+ // src/effects/handlers/retain-ability-change.ts
475
+ var applyRetainAbilityChange = createEffectHandler("RETAIN_ABILITY_CHANGE", ({
476
+ effect,
477
+ payloads,
478
+ makePlayersEffect
479
+ }) => {
480
+ const value = getSourceValue(effect.source, payloads);
481
+ if (value === "ALIVENESS" || value === "ALL") {
482
+ makePlayersEffect.forEach((player) => {
483
+ player.retainsAbility = value;
484
+ });
485
+ return;
486
+ }
487
+ if (value === "NONE") {
488
+ makePlayersEffect.forEach((player) => {
489
+ delete player.retainsAbility;
490
+ });
491
+ return;
492
+ }
493
+ console.warn("Invalid value for RETAIN_ABILITY_CHANGE effect:", value);
494
+ });
495
+
474
496
  // src/effects/handlers/seat-change.ts
475
497
  var applySeatChange = createEffectHandler("SEAT_CHANGE", () => {
476
498
  console.warn("SEAT_CHANGE effect handling not implemented yet.");
@@ -518,6 +540,7 @@ var effectHandlers = {
518
540
  PERCEIVED_CHARACTER_CHANGE: applyPerceivedCharacterChange,
519
541
  REMINDER_ADD: applyReminderAdd,
520
542
  REMINDER_REMOVE: applyReminderRemove,
543
+ RETAIN_ABILITY_CHANGE: applyRetainAbilityChange,
521
544
  SEAT_CHANGE: applySeatChange,
522
545
  STATUS_CHANGE: applyStatusChange
523
546
  };
@@ -589,22 +612,22 @@ var getCandidatesBySelector = (dynamicTarget, sortedPlayers, anchorSeat, payload
589
612
  if (scope === "LEFT_SIDE") {
590
613
  const left2 = [];
591
614
  for (let step = 1; step < total; step += 1) {
592
- left2.push(sortedPlayers[(anchorIdx - step + total) % total]);
615
+ left2.push(sortedPlayers[(anchorIdx + step) % total]);
593
616
  }
594
617
  return left2;
595
618
  }
596
619
  if (scope === "RIGHT_SIDE") {
597
620
  const right2 = [];
598
621
  for (let step = 1; step < total; step += 1) {
599
- right2.push(sortedPlayers[(anchorIdx + step) % total]);
622
+ right2.push(sortedPlayers[(anchorIdx - step + total) % total]);
600
623
  }
601
624
  return right2;
602
625
  }
603
626
  const left = [];
604
627
  const right = [];
605
628
  for (let step = 1; step < total; step += 1) {
606
- left.push(sortedPlayers[(anchorIdx - step + total) % total]);
607
- right.push(sortedPlayers[(anchorIdx + step) % total]);
629
+ left.push(sortedPlayers[(anchorIdx + step) % total]);
630
+ right.push(sortedPlayers[(anchorIdx - step + total) % total]);
608
631
  }
609
632
  return [...left, ...right];
610
633
  };
@@ -1318,7 +1341,8 @@ var evalAtomState = (atom, ctx) => {
1318
1341
  const player = ctx.players.find((p) => p.seat === seat);
1319
1342
  if (!player) continue;
1320
1343
  const isDead = Boolean(player.isDead);
1321
- if (atom.aliveness === "ALIVE" && isDead) continue;
1344
+ const bypassAlive = isDead && (player.retainsAbility === "ALIVENESS" || player.retainsAbility === "ALL");
1345
+ if (atom.aliveness === "ALIVE" && isDead && !bypassAlive) continue;
1322
1346
  if (atom.aliveness === "DEAD" && !isDead) continue;
1323
1347
  if (atom.aliveness === "DEAD") {
1324
1348
  if (atom.deathCause && player.deathCause !== atom.deathCause) continue;
@@ -1465,6 +1489,9 @@ var canInvokeAbility = ({
1465
1489
  if ("error" in derived) {
1466
1490
  return { allowed: false, reason: derived.error };
1467
1491
  }
1492
+ if (derived.effector?.retainsAbility === "ALL") {
1493
+ return { allowed: true };
1494
+ }
1468
1495
  const reason = evalExpr2(window, derived, customResolver);
1469
1496
  return reason ? { allowed: false, reason } : { allowed: true };
1470
1497
  };
package/dist/index.mjs CHANGED
@@ -431,6 +431,28 @@ var applyReminderRemove = createEffectHandler("REMINDER_REMOVE", ({ effect, payl
431
431
  });
432
432
  });
433
433
 
434
+ // src/effects/handlers/retain-ability-change.ts
435
+ var applyRetainAbilityChange = createEffectHandler("RETAIN_ABILITY_CHANGE", ({
436
+ effect,
437
+ payloads,
438
+ makePlayersEffect
439
+ }) => {
440
+ const value = getSourceValue(effect.source, payloads);
441
+ if (value === "ALIVENESS" || value === "ALL") {
442
+ makePlayersEffect.forEach((player) => {
443
+ player.retainsAbility = value;
444
+ });
445
+ return;
446
+ }
447
+ if (value === "NONE") {
448
+ makePlayersEffect.forEach((player) => {
449
+ delete player.retainsAbility;
450
+ });
451
+ return;
452
+ }
453
+ console.warn("Invalid value for RETAIN_ABILITY_CHANGE effect:", value);
454
+ });
455
+
434
456
  // src/effects/handlers/seat-change.ts
435
457
  var applySeatChange = createEffectHandler("SEAT_CHANGE", () => {
436
458
  console.warn("SEAT_CHANGE effect handling not implemented yet.");
@@ -478,6 +500,7 @@ var effectHandlers = {
478
500
  PERCEIVED_CHARACTER_CHANGE: applyPerceivedCharacterChange,
479
501
  REMINDER_ADD: applyReminderAdd,
480
502
  REMINDER_REMOVE: applyReminderRemove,
503
+ RETAIN_ABILITY_CHANGE: applyRetainAbilityChange,
481
504
  SEAT_CHANGE: applySeatChange,
482
505
  STATUS_CHANGE: applyStatusChange
483
506
  };
@@ -549,22 +572,22 @@ var getCandidatesBySelector = (dynamicTarget, sortedPlayers, anchorSeat, payload
549
572
  if (scope === "LEFT_SIDE") {
550
573
  const left2 = [];
551
574
  for (let step = 1; step < total; step += 1) {
552
- left2.push(sortedPlayers[(anchorIdx - step + total) % total]);
575
+ left2.push(sortedPlayers[(anchorIdx + step) % total]);
553
576
  }
554
577
  return left2;
555
578
  }
556
579
  if (scope === "RIGHT_SIDE") {
557
580
  const right2 = [];
558
581
  for (let step = 1; step < total; step += 1) {
559
- right2.push(sortedPlayers[(anchorIdx + step) % total]);
582
+ right2.push(sortedPlayers[(anchorIdx - step + total) % total]);
560
583
  }
561
584
  return right2;
562
585
  }
563
586
  const left = [];
564
587
  const right = [];
565
588
  for (let step = 1; step < total; step += 1) {
566
- left.push(sortedPlayers[(anchorIdx - step + total) % total]);
567
- right.push(sortedPlayers[(anchorIdx + step) % total]);
589
+ left.push(sortedPlayers[(anchorIdx + step) % total]);
590
+ right.push(sortedPlayers[(anchorIdx - step + total) % total]);
568
591
  }
569
592
  return [...left, ...right];
570
593
  };
@@ -1278,7 +1301,8 @@ var evalAtomState = (atom, ctx) => {
1278
1301
  const player = ctx.players.find((p) => p.seat === seat);
1279
1302
  if (!player) continue;
1280
1303
  const isDead = Boolean(player.isDead);
1281
- if (atom.aliveness === "ALIVE" && isDead) continue;
1304
+ const bypassAlive = isDead && (player.retainsAbility === "ALIVENESS" || player.retainsAbility === "ALL");
1305
+ if (atom.aliveness === "ALIVE" && isDead && !bypassAlive) continue;
1282
1306
  if (atom.aliveness === "DEAD" && !isDead) continue;
1283
1307
  if (atom.aliveness === "DEAD") {
1284
1308
  if (atom.deathCause && player.deathCause !== atom.deathCause) continue;
@@ -1425,6 +1449,9 @@ var canInvokeAbility = ({
1425
1449
  if ("error" in derived) {
1426
1450
  return { allowed: false, reason: derived.error };
1427
1451
  }
1452
+ if (derived.effector?.retainsAbility === "ALL") {
1453
+ return { allowed: true };
1454
+ }
1428
1455
  const reason = evalExpr2(window, derived, customResolver);
1429
1456
  return reason ? { allowed: false, reason } : { allowed: true };
1430
1457
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bct-app/game-engine",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
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.5"
33
+ "@bct-app/game-model": "0.1.6"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@vitest/ui": "^4.1.3",