koishipro-core.js 1.2.4 → 1.2.5

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.cjs CHANGED
@@ -53,6 +53,7 @@ __export(index_exports, {
53
53
  PlayerViewAdvancor: () => PlayerViewAdvancor,
54
54
  QUERY_BUFFER_SIZE: () => QUERY_BUFFER_SIZE,
55
55
  REGISTRY_BUFFER_SIZE: () => REGISTRY_BUFFER_SIZE,
56
+ SelectCardAdvancor: () => SelectCardAdvancor,
56
57
  SlientAdvancor: () => SlientAdvancor,
57
58
  SqljsCardReader: () => SqljsCardReader,
58
59
  StaticAdvancor: () => StaticAdvancor,
@@ -1496,6 +1497,205 @@ var SummonPlaceAdvancor = (placeAndPosition = {}) => MapAdvancor(
1496
1497
  })
1497
1498
  );
1498
1499
 
1500
+ // src/advancors/select-card-advancor.ts
1501
+ var import_ygopro_msg_encode8 = require("ygopro-msg-encode");
1502
+ var SelectCardAdvancor = (...cards) => {
1503
+ const remainingCards = cards.slice();
1504
+ const applyFilter = (items, filter) => {
1505
+ return items.filter(
1506
+ (item) => Object.entries(filter).every(
1507
+ ([key, value]) => value == null || item[key] === value
1508
+ )
1509
+ );
1510
+ };
1511
+ const pickCard = (items, min, max) => {
1512
+ const picked = [];
1513
+ const usedIndices = /* @__PURE__ */ new Set();
1514
+ const usedFilters = /* @__PURE__ */ new Set();
1515
+ for (const filter of remainingCards) {
1516
+ if (picked.length >= max) break;
1517
+ let matchIndex = -1;
1518
+ for (let i = 0; i < items.length; i++) {
1519
+ if (usedIndices.has(i)) continue;
1520
+ if (applyFilter([items[i]], filter).length === 1) {
1521
+ matchIndex = i;
1522
+ break;
1523
+ }
1524
+ }
1525
+ if (matchIndex < 0) continue;
1526
+ picked.push((0, import_ygopro_msg_encode8.IndexResponse)(matchIndex));
1527
+ usedIndices.add(matchIndex);
1528
+ usedFilters.add(filter);
1529
+ }
1530
+ if (picked.length < min) {
1531
+ return void 0;
1532
+ }
1533
+ for (let i = remainingCards.length - 1; i >= 0; i--) {
1534
+ if (usedFilters.has(remainingCards[i])) {
1535
+ remainingCards.splice(i, 1);
1536
+ }
1537
+ }
1538
+ return picked;
1539
+ };
1540
+ return MapAdvancor(
1541
+ MapAdvancorHandler(import_ygopro_msg_encode8.YGOProMsgSelectCard, (msg) => {
1542
+ const picked = pickCard(msg.cards, msg.min, msg.max);
1543
+ if (picked) {
1544
+ return msg.prepareResponse(picked);
1545
+ }
1546
+ }),
1547
+ MapAdvancorHandler(import_ygopro_msg_encode8.YGOProMsgSelectUnselectCard, (msg) => {
1548
+ const picked = pickCard(msg.selectableCards, 1, 1);
1549
+ if (picked) {
1550
+ return msg.prepareResponse(picked[0]);
1551
+ }
1552
+ }),
1553
+ MapAdvancorHandler(import_ygopro_msg_encode8.YGOProMsgSelectSum, (msg) => {
1554
+ const decodeOpParam = (opParam) => {
1555
+ const u = opParam >>> 0;
1556
+ if ((u & 2147483648) !== 0) {
1557
+ return { amount: u & 2147483647, extra: 0 };
1558
+ }
1559
+ return { amount: u & 65535, extra: u >>> 16 & 65535 };
1560
+ };
1561
+ const amountOf = (c) => decodeOpParam(c.opParam).amount;
1562
+ const mustSum = (msg.mustSelectCards ?? []).reduce(
1563
+ (acc, c) => acc + amountOf(c),
1564
+ 0
1565
+ );
1566
+ const mustCount = (msg.mustSelectCards ?? []).length;
1567
+ const pickedIdx = [];
1568
+ const pickedIdxSet = /* @__PURE__ */ new Set();
1569
+ const totalSum = () => mustSum + pickedIdx.reduce((acc, i) => acc + amountOf(msg.cards[i]), 0);
1570
+ const totalCount = () => mustCount + pickedIdx.length;
1571
+ const filterMatch = /* @__PURE__ */ new Map();
1572
+ for (let fi = 0; fi < remainingCards.length; fi++) {
1573
+ const f = remainingCards[fi];
1574
+ const idx = msg.cards.findIndex(
1575
+ (c, i) => !pickedIdxSet.has(i) && applyFilter([c], f).length === 1
1576
+ );
1577
+ if (idx < 0) continue;
1578
+ pickedIdx.push(idx);
1579
+ pickedIdxSet.add(idx);
1580
+ filterMatch.set(fi, idx);
1581
+ }
1582
+ const consumeRemainingByFinalPick = () => {
1583
+ const usedFilterIdx = /* @__PURE__ */ new Set();
1584
+ for (const [fi, idx] of filterMatch.entries()) {
1585
+ if (pickedIdxSet.has(idx)) usedFilterIdx.add(fi);
1586
+ }
1587
+ for (let i = remainingCards.length - 1; i >= 0; i--) {
1588
+ if (usedFilterIdx.has(i)) remainingCards.splice(i, 1);
1589
+ }
1590
+ };
1591
+ const target = msg.sumVal;
1592
+ if (msg.mode === 1) {
1593
+ let s = totalSum();
1594
+ if (s < target) {
1595
+ for (let i = 0; i < msg.cards.length; i++) {
1596
+ if (s >= target) break;
1597
+ if (pickedIdxSet.has(i)) continue;
1598
+ pickedIdx.push(i);
1599
+ pickedIdxSet.add(i);
1600
+ s += amountOf(msg.cards[i]);
1601
+ }
1602
+ }
1603
+ if (s < target) return;
1604
+ const removable = (pos) => {
1605
+ const idx = pickedIdx[pos];
1606
+ const v = amountOf(msg.cards[idx]);
1607
+ return s - v >= target;
1608
+ };
1609
+ for (let pos = pickedIdx.length - 1; pos >= 0; pos--) {
1610
+ if (!removable(pos)) continue;
1611
+ const idx = pickedIdx[pos];
1612
+ const v = amountOf(msg.cards[idx]);
1613
+ pickedIdx.splice(pos, 1);
1614
+ pickedIdxSet.delete(idx);
1615
+ s -= v;
1616
+ }
1617
+ for (const idx of pickedIdx) {
1618
+ if (s - amountOf(msg.cards[idx]) >= target) return;
1619
+ }
1620
+ consumeRemainingByFinalPick();
1621
+ return msg.prepareResponse(pickedIdx.map((i) => (0, import_ygopro_msg_encode8.IndexResponse)(i)));
1622
+ }
1623
+ const baseSum = mustSum;
1624
+ const baseCount = mustCount;
1625
+ const sumLeft = target - baseSum;
1626
+ const minLeft = Math.max(0, msg.min - baseCount);
1627
+ const maxLeft = Math.max(0, msg.max - baseCount);
1628
+ if (sumLeft < 0) return;
1629
+ if (maxLeft < 0) return;
1630
+ const preSum = pickedIdx.reduce(
1631
+ (acc, i) => acc + amountOf(msg.cards[i]),
1632
+ 0
1633
+ );
1634
+ const preCount = pickedIdx.length;
1635
+ const sumNeed = sumLeft - preSum;
1636
+ const minNeed = Math.max(0, minLeft - preCount);
1637
+ const maxNeed = Math.max(0, maxLeft - preCount);
1638
+ if (sumNeed < 0) return;
1639
+ if (maxNeed < 0) return;
1640
+ const candidates = [];
1641
+ for (let i = 0; i < msg.cards.length; i++) {
1642
+ if (pickedIdxSet.has(i)) continue;
1643
+ const v = amountOf(msg.cards[i]);
1644
+ if (v <= sumNeed) candidates.push({ idx: i, v });
1645
+ }
1646
+ const keyOf = (sum, cnt) => `${sum}|${cnt}`;
1647
+ const dp = /* @__PURE__ */ new Map();
1648
+ dp.set(keyOf(0, 0), {});
1649
+ for (const c of candidates) {
1650
+ const snapshot = Array.from(dp.keys());
1651
+ for (const k of snapshot) {
1652
+ const [sStr, cStr] = k.split("|");
1653
+ const s = Number(sStr);
1654
+ const cnt = Number(cStr);
1655
+ const ns = s + c.v;
1656
+ const ncnt = cnt + 1;
1657
+ if (ns > sumNeed) continue;
1658
+ if (ncnt > maxNeed) continue;
1659
+ const nk = keyOf(ns, ncnt);
1660
+ if (dp.has(nk)) continue;
1661
+ dp.set(nk, { prevKey: k, takeIdx: c.idx });
1662
+ }
1663
+ }
1664
+ let bestKey;
1665
+ for (let cnt = minNeed; cnt <= maxNeed; cnt++) {
1666
+ const k = keyOf(sumNeed, cnt);
1667
+ if (dp.has(k)) {
1668
+ bestKey = k;
1669
+ break;
1670
+ }
1671
+ }
1672
+ if (!bestKey) return;
1673
+ const extraIdx = [];
1674
+ let curKey = bestKey;
1675
+ while (curKey !== keyOf(0, 0)) {
1676
+ const node = dp.get(curKey);
1677
+ if (typeof node.takeIdx === "number") extraIdx.push(node.takeIdx);
1678
+ curKey = node.prevKey;
1679
+ }
1680
+ extraIdx.reverse();
1681
+ for (const i of extraIdx) {
1682
+ pickedIdx.push(i);
1683
+ pickedIdxSet.add(i);
1684
+ }
1685
+ if (totalCount() < msg.min || totalCount() > msg.max) return;
1686
+ if (totalSum() !== target) return;
1687
+ consumeRemainingByFinalPick();
1688
+ return msg.prepareResponse(pickedIdx.map((i) => (0, import_ygopro_msg_encode8.IndexResponse)(i)));
1689
+ }),
1690
+ MapAdvancorHandler(import_ygopro_msg_encode8.YGOProMsgSelectTribute, (msg) => {
1691
+ const picked = pickCard(msg.cards, msg.min, msg.max);
1692
+ if (picked) {
1693
+ return msg.prepareResponse(picked);
1694
+ }
1695
+ })
1696
+ );
1697
+ };
1698
+
1499
1699
  // index.ts
1500
1700
  if (typeof globalThis !== "undefined" && !globalThis.Buffer) {
1501
1701
  globalThis.Buffer = import_buffer.Buffer;
@@ -1526,6 +1726,7 @@ if (typeof globalThis !== "undefined" && !globalThis.Buffer) {
1526
1726
  PlayerViewAdvancor,
1527
1727
  QUERY_BUFFER_SIZE,
1528
1728
  REGISTRY_BUFFER_SIZE,
1729
+ SelectCardAdvancor,
1529
1730
  SlientAdvancor,
1530
1731
  SqljsCardReader,
1531
1732
  StaticAdvancor,