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.mjs CHANGED
@@ -1410,6 +1410,211 @@ var SummonPlaceAdvancor = (placeAndPosition = {}) => MapAdvancor(
1410
1410
  })
1411
1411
  );
1412
1412
 
1413
+ // src/advancors/select-card-advancor.ts
1414
+ import {
1415
+ IndexResponse,
1416
+ YGOProMsgSelectCard,
1417
+ YGOProMsgSelectSum,
1418
+ YGOProMsgSelectTribute,
1419
+ YGOProMsgSelectUnselectCard
1420
+ } from "ygopro-msg-encode";
1421
+ var SelectCardAdvancor = (...cards) => {
1422
+ const remainingCards = cards.slice();
1423
+ const applyFilter = (items, filter) => {
1424
+ return items.filter(
1425
+ (item) => Object.entries(filter).every(
1426
+ ([key, value]) => value == null || item[key] === value
1427
+ )
1428
+ );
1429
+ };
1430
+ const pickCard = (items, min, max) => {
1431
+ const picked = [];
1432
+ const usedIndices = /* @__PURE__ */ new Set();
1433
+ const usedFilters = /* @__PURE__ */ new Set();
1434
+ for (const filter of remainingCards) {
1435
+ if (picked.length >= max) break;
1436
+ let matchIndex = -1;
1437
+ for (let i = 0; i < items.length; i++) {
1438
+ if (usedIndices.has(i)) continue;
1439
+ if (applyFilter([items[i]], filter).length === 1) {
1440
+ matchIndex = i;
1441
+ break;
1442
+ }
1443
+ }
1444
+ if (matchIndex < 0) continue;
1445
+ picked.push(IndexResponse(matchIndex));
1446
+ usedIndices.add(matchIndex);
1447
+ usedFilters.add(filter);
1448
+ }
1449
+ if (picked.length < min) {
1450
+ return void 0;
1451
+ }
1452
+ for (let i = remainingCards.length - 1; i >= 0; i--) {
1453
+ if (usedFilters.has(remainingCards[i])) {
1454
+ remainingCards.splice(i, 1);
1455
+ }
1456
+ }
1457
+ return picked;
1458
+ };
1459
+ return MapAdvancor(
1460
+ MapAdvancorHandler(YGOProMsgSelectCard, (msg) => {
1461
+ const picked = pickCard(msg.cards, msg.min, msg.max);
1462
+ if (picked) {
1463
+ return msg.prepareResponse(picked);
1464
+ }
1465
+ }),
1466
+ MapAdvancorHandler(YGOProMsgSelectUnselectCard, (msg) => {
1467
+ const picked = pickCard(msg.selectableCards, 1, 1);
1468
+ if (picked) {
1469
+ return msg.prepareResponse(picked[0]);
1470
+ }
1471
+ }),
1472
+ MapAdvancorHandler(YGOProMsgSelectSum, (msg) => {
1473
+ const decodeOpParam = (opParam) => {
1474
+ const u = opParam >>> 0;
1475
+ if ((u & 2147483648) !== 0) {
1476
+ return { amount: u & 2147483647, extra: 0 };
1477
+ }
1478
+ return { amount: u & 65535, extra: u >>> 16 & 65535 };
1479
+ };
1480
+ const amountOf = (c) => decodeOpParam(c.opParam).amount;
1481
+ const mustSum = (msg.mustSelectCards ?? []).reduce(
1482
+ (acc, c) => acc + amountOf(c),
1483
+ 0
1484
+ );
1485
+ const mustCount = (msg.mustSelectCards ?? []).length;
1486
+ const pickedIdx = [];
1487
+ const pickedIdxSet = /* @__PURE__ */ new Set();
1488
+ const totalSum = () => mustSum + pickedIdx.reduce((acc, i) => acc + amountOf(msg.cards[i]), 0);
1489
+ const totalCount = () => mustCount + pickedIdx.length;
1490
+ const filterMatch = /* @__PURE__ */ new Map();
1491
+ for (let fi = 0; fi < remainingCards.length; fi++) {
1492
+ const f = remainingCards[fi];
1493
+ const idx = msg.cards.findIndex(
1494
+ (c, i) => !pickedIdxSet.has(i) && applyFilter([c], f).length === 1
1495
+ );
1496
+ if (idx < 0) continue;
1497
+ pickedIdx.push(idx);
1498
+ pickedIdxSet.add(idx);
1499
+ filterMatch.set(fi, idx);
1500
+ }
1501
+ const consumeRemainingByFinalPick = () => {
1502
+ const usedFilterIdx = /* @__PURE__ */ new Set();
1503
+ for (const [fi, idx] of filterMatch.entries()) {
1504
+ if (pickedIdxSet.has(idx)) usedFilterIdx.add(fi);
1505
+ }
1506
+ for (let i = remainingCards.length - 1; i >= 0; i--) {
1507
+ if (usedFilterIdx.has(i)) remainingCards.splice(i, 1);
1508
+ }
1509
+ };
1510
+ const target = msg.sumVal;
1511
+ if (msg.mode === 1) {
1512
+ let s = totalSum();
1513
+ if (s < target) {
1514
+ for (let i = 0; i < msg.cards.length; i++) {
1515
+ if (s >= target) break;
1516
+ if (pickedIdxSet.has(i)) continue;
1517
+ pickedIdx.push(i);
1518
+ pickedIdxSet.add(i);
1519
+ s += amountOf(msg.cards[i]);
1520
+ }
1521
+ }
1522
+ if (s < target) return;
1523
+ const removable = (pos) => {
1524
+ const idx = pickedIdx[pos];
1525
+ const v = amountOf(msg.cards[idx]);
1526
+ return s - v >= target;
1527
+ };
1528
+ for (let pos = pickedIdx.length - 1; pos >= 0; pos--) {
1529
+ if (!removable(pos)) continue;
1530
+ const idx = pickedIdx[pos];
1531
+ const v = amountOf(msg.cards[idx]);
1532
+ pickedIdx.splice(pos, 1);
1533
+ pickedIdxSet.delete(idx);
1534
+ s -= v;
1535
+ }
1536
+ for (const idx of pickedIdx) {
1537
+ if (s - amountOf(msg.cards[idx]) >= target) return;
1538
+ }
1539
+ consumeRemainingByFinalPick();
1540
+ return msg.prepareResponse(pickedIdx.map((i) => IndexResponse(i)));
1541
+ }
1542
+ const baseSum = mustSum;
1543
+ const baseCount = mustCount;
1544
+ const sumLeft = target - baseSum;
1545
+ const minLeft = Math.max(0, msg.min - baseCount);
1546
+ const maxLeft = Math.max(0, msg.max - baseCount);
1547
+ if (sumLeft < 0) return;
1548
+ if (maxLeft < 0) return;
1549
+ const preSum = pickedIdx.reduce(
1550
+ (acc, i) => acc + amountOf(msg.cards[i]),
1551
+ 0
1552
+ );
1553
+ const preCount = pickedIdx.length;
1554
+ const sumNeed = sumLeft - preSum;
1555
+ const minNeed = Math.max(0, minLeft - preCount);
1556
+ const maxNeed = Math.max(0, maxLeft - preCount);
1557
+ if (sumNeed < 0) return;
1558
+ if (maxNeed < 0) return;
1559
+ const candidates = [];
1560
+ for (let i = 0; i < msg.cards.length; i++) {
1561
+ if (pickedIdxSet.has(i)) continue;
1562
+ const v = amountOf(msg.cards[i]);
1563
+ if (v <= sumNeed) candidates.push({ idx: i, v });
1564
+ }
1565
+ const keyOf = (sum, cnt) => `${sum}|${cnt}`;
1566
+ const dp = /* @__PURE__ */ new Map();
1567
+ dp.set(keyOf(0, 0), {});
1568
+ for (const c of candidates) {
1569
+ const snapshot = Array.from(dp.keys());
1570
+ for (const k of snapshot) {
1571
+ const [sStr, cStr] = k.split("|");
1572
+ const s = Number(sStr);
1573
+ const cnt = Number(cStr);
1574
+ const ns = s + c.v;
1575
+ const ncnt = cnt + 1;
1576
+ if (ns > sumNeed) continue;
1577
+ if (ncnt > maxNeed) continue;
1578
+ const nk = keyOf(ns, ncnt);
1579
+ if (dp.has(nk)) continue;
1580
+ dp.set(nk, { prevKey: k, takeIdx: c.idx });
1581
+ }
1582
+ }
1583
+ let bestKey;
1584
+ for (let cnt = minNeed; cnt <= maxNeed; cnt++) {
1585
+ const k = keyOf(sumNeed, cnt);
1586
+ if (dp.has(k)) {
1587
+ bestKey = k;
1588
+ break;
1589
+ }
1590
+ }
1591
+ if (!bestKey) return;
1592
+ const extraIdx = [];
1593
+ let curKey = bestKey;
1594
+ while (curKey !== keyOf(0, 0)) {
1595
+ const node = dp.get(curKey);
1596
+ if (typeof node.takeIdx === "number") extraIdx.push(node.takeIdx);
1597
+ curKey = node.prevKey;
1598
+ }
1599
+ extraIdx.reverse();
1600
+ for (const i of extraIdx) {
1601
+ pickedIdx.push(i);
1602
+ pickedIdxSet.add(i);
1603
+ }
1604
+ if (totalCount() < msg.min || totalCount() > msg.max) return;
1605
+ if (totalSum() !== target) return;
1606
+ consumeRemainingByFinalPick();
1607
+ return msg.prepareResponse(pickedIdx.map((i) => IndexResponse(i)));
1608
+ }),
1609
+ MapAdvancorHandler(YGOProMsgSelectTribute, (msg) => {
1610
+ const picked = pickCard(msg.cards, msg.min, msg.max);
1611
+ if (picked) {
1612
+ return msg.prepareResponse(picked);
1613
+ }
1614
+ })
1615
+ );
1616
+ };
1617
+
1413
1618
  // index.ts
1414
1619
  if (typeof globalThis !== "undefined" && !globalThis.Buffer) {
1415
1620
  globalThis.Buffer = Buffer2;
@@ -1439,6 +1644,7 @@ export {
1439
1644
  PlayerViewAdvancor,
1440
1645
  QUERY_BUFFER_SIZE,
1441
1646
  REGISTRY_BUFFER_SIZE,
1647
+ SelectCardAdvancor,
1442
1648
  SlientAdvancor,
1443
1649
  SqljsCardReader,
1444
1650
  StaticAdvancor,