koishipro-core.js 1.2.3 → 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/README.md +75 -0
- package/dist/index.cjs +334 -1
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +332 -1
- package/dist/index.mjs.map +3 -3
- package/dist/src/advancors/combined-advancor.d.ts +2 -0
- package/dist/src/advancors/index.d.ts +10 -0
- package/dist/src/advancors/limit-advancor.d.ts +4 -0
- package/dist/src/advancors/map-advancor.d.ts +8 -0
- package/dist/src/advancors/no-effect-advancor.d.ts +1 -0
- package/dist/src/advancors/player-view-advancor.d.ts +3 -0
- package/dist/src/advancors/select-card-advancor.d.ts +7 -0
- package/dist/src/advancors/slient-advancor.d.ts +2 -0
- package/dist/src/advancors/static-advancor.d.ts +2 -0
- package/dist/src/advancors/summon-place-advancor.d.ts +5 -0
- package/dist/src/advancors/types.d.ts +2 -0
- package/dist/src/ocgcore-duel.d.ts +2 -1
- package/dist/src/play-yrp.d.ts +1 -2
- package/dist/src/types/card-location.d.ts +5 -0
- package/dist/src/types/index.d.ts +1 -0
- package/index.ts +1 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -162,6 +162,26 @@ Represents a single duel instance with full lifecycle management.
|
|
|
162
162
|
- `endDuel(): void`
|
|
163
163
|
End the duel and clean up resources.
|
|
164
164
|
|
|
165
|
+
**Advance Helpers (Advancors):**
|
|
166
|
+
- `advance(advancor?: Advancor): Generator<OcgcoreProcessResult>`
|
|
167
|
+
Advances the duel processing loop. It repeatedly calls `process()`, and when a response is required, it invokes your advancor. It stops when the duel ends, a retry is requested, or your advancor returns `undefined`.
|
|
168
|
+
|
|
169
|
+
**Example (Advance + Advancor)**
|
|
170
|
+
```ts
|
|
171
|
+
import { createOcgcoreWrapper, SlientAdvancor } from 'koishipro-core.js';
|
|
172
|
+
|
|
173
|
+
const wrapper = await createOcgcoreWrapper();
|
|
174
|
+
// ...setScriptReader / setCardReader / create duel / start duel...
|
|
175
|
+
|
|
176
|
+
const duel = wrapper.createDuel(1234);
|
|
177
|
+
|
|
178
|
+
for (const result of duel.advance(SlientAdvancor())) {
|
|
179
|
+
if (result.message) {
|
|
180
|
+
console.log(result.message);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
165
185
|
**Card Management:**
|
|
166
186
|
- `newCard(card: OcgcoreNewCardParams): void`
|
|
167
187
|
Add a card to the duel.
|
|
@@ -267,6 +287,61 @@ for (const { duel, result } of playYrpStep(wrapper, yrpBytes)) {
|
|
|
267
287
|
}
|
|
268
288
|
```
|
|
269
289
|
|
|
290
|
+
|
|
291
|
+
### Advancors
|
|
292
|
+
Advancors are small response producers. You pass them into `duel.advance(...)` and they auto-generate response bytes for the current message. If multiple advancors are combined, the first one that returns a response wins.
|
|
293
|
+
|
|
294
|
+
**Type**
|
|
295
|
+
```ts
|
|
296
|
+
import { YGOProMsgResponseBase } from 'ygopro-msg-encode';
|
|
297
|
+
|
|
298
|
+
export type Advancor<T extends YGOProMsgResponseBase = YGOProMsgResponseBase> =
|
|
299
|
+
(message: T) => Uint8Array | null | undefined;
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
#### `SlientAdvancor()`
|
|
303
|
+
Calls `defaultResponse()` for any message. In practice, this auto-answers optional effect prompts with “do not activate” and is ideal for fast-forwarding.
|
|
304
|
+
|
|
305
|
+
#### `NoEffectAdvancor()`
|
|
306
|
+
Only responds to `SelectChain` when there are **no** chains available, allowing the duel to continue. It does not auto-decline effect prompts. Use this when you want to handle effect prompts yourself.
|
|
307
|
+
|
|
308
|
+
#### `SummonPlaceAdvancor(placeAndPosition?)`
|
|
309
|
+
Auto-selects summon placement (`SelectPlace`) and position (`SelectPosition`). You can pass a partial filter to constrain player/location/sequence/position.
|
|
310
|
+
|
|
311
|
+
#### `SelectCardAdvancor(...filters)`
|
|
312
|
+
Selects cards by matching filters (e.g., code, location, controller). Supports several message types like `SelectCard`, `SelectUnselectCard`, `SelectSum`, `SelectTribute`.
|
|
313
|
+
|
|
314
|
+
#### `StaticAdvancor(items)`
|
|
315
|
+
Returns a fixed sequence of responses you provide. Each call consumes one item.
|
|
316
|
+
|
|
317
|
+
#### `CombinedAdvancor(...advancors)`
|
|
318
|
+
Runs advancors in order and returns the first non-`undefined` response. This is the same combiner used by `advance(...)` internally.
|
|
319
|
+
|
|
320
|
+
#### `MapAdvancor(...handlers)`
|
|
321
|
+
Dispatches by message class. Each handler maps a message type to an advancor function.
|
|
322
|
+
|
|
323
|
+
#### `MapAdvancorHandler(msgClass, cb)`
|
|
324
|
+
Helper for building `MapAdvancor` handler objects.
|
|
325
|
+
|
|
326
|
+
#### `LimitAdvancor(advancor, limit)`
|
|
327
|
+
Wraps an advancor and only allows it to return a response `limit` times.
|
|
328
|
+
|
|
329
|
+
#### `OnceAdvancor(advancor)`
|
|
330
|
+
Shorthand for `LimitAdvancor(advancor, 1)`.
|
|
331
|
+
|
|
332
|
+
#### `PlayerViewAdvancor(player, advancor)`
|
|
333
|
+
Runs the inner advancor only when `responsePlayer()` matches the specified player.
|
|
334
|
+
|
|
335
|
+
#### Composition
|
|
336
|
+
You can combine advancors to form a pipeline:
|
|
337
|
+
```ts
|
|
338
|
+
duel.advance(
|
|
339
|
+
SlientAdvancor(),
|
|
340
|
+
SummonPlaceAdvancor(),
|
|
341
|
+
SelectCardAdvancor({ code: 28985331 }),
|
|
342
|
+
);
|
|
343
|
+
```
|
|
344
|
+
|
|
270
345
|
### Card Reader
|
|
271
346
|
|
|
272
347
|
#### `SqljsCardReader(...dbs: Database[]): CardReader`
|
package/dist/index.cjs
CHANGED
|
@@ -29,6 +29,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
29
29
|
// index.ts
|
|
30
30
|
var index_exports = {};
|
|
31
31
|
__export(index_exports, {
|
|
32
|
+
CombinedAdvancor: () => CombinedAdvancor,
|
|
32
33
|
DirCardReader: () => DirCardReader,
|
|
33
34
|
DirReader: () => DirReader,
|
|
34
35
|
DirScriptReader: () => DirScriptReader,
|
|
@@ -36,17 +37,27 @@ __export(index_exports, {
|
|
|
36
37
|
LEN_EMPTY: () => LEN_EMPTY,
|
|
37
38
|
LEN_FAIL: () => LEN_FAIL,
|
|
38
39
|
LEN_HEADER: () => LEN_HEADER,
|
|
40
|
+
LimitAdvancor: () => LimitAdvancor,
|
|
39
41
|
MESSAGE_BUFFER_SIZE: () => MESSAGE_BUFFER_SIZE,
|
|
42
|
+
MapAdvancor: () => MapAdvancor,
|
|
43
|
+
MapAdvancorHandler: () => MapAdvancorHandler,
|
|
40
44
|
MapReader: () => MapReader,
|
|
41
45
|
MapScriptReader: () => MapScriptReader,
|
|
46
|
+
NoEffectAdvancor: () => NoEffectAdvancor,
|
|
42
47
|
OcgcoreDuel: () => OcgcoreDuel,
|
|
43
48
|
OcgcoreDuelOptionFlag: () => OcgcoreDuelOptionFlag,
|
|
44
49
|
OcgcoreDuelRule: () => OcgcoreDuelRule,
|
|
45
50
|
OcgcoreMessageType: () => OcgcoreMessageType,
|
|
46
51
|
OcgcoreWrapper: () => OcgcoreWrapper,
|
|
52
|
+
OnceAdvancor: () => OnceAdvancor,
|
|
53
|
+
PlayerViewAdvancor: () => PlayerViewAdvancor,
|
|
47
54
|
QUERY_BUFFER_SIZE: () => QUERY_BUFFER_SIZE,
|
|
48
55
|
REGISTRY_BUFFER_SIZE: () => REGISTRY_BUFFER_SIZE,
|
|
56
|
+
SelectCardAdvancor: () => SelectCardAdvancor,
|
|
57
|
+
SlientAdvancor: () => SlientAdvancor,
|
|
49
58
|
SqljsCardReader: () => SqljsCardReader,
|
|
59
|
+
StaticAdvancor: () => StaticAdvancor,
|
|
60
|
+
SummonPlaceAdvancor: () => SummonPlaceAdvancor,
|
|
50
61
|
ZipReader: () => ZipReader,
|
|
51
62
|
ZipScriptReader: () => ZipScriptReader,
|
|
52
63
|
_OcgcoreConstants: () => vendor_exports,
|
|
@@ -267,7 +278,7 @@ var OcgcoreDuel = class {
|
|
|
267
278
|
break;
|
|
268
279
|
}
|
|
269
280
|
if (res.status === 1 && res.raw.length > 0) {
|
|
270
|
-
const response = advancor?.();
|
|
281
|
+
const response = advancor?.(res.message);
|
|
271
282
|
if (!response) {
|
|
272
283
|
break;
|
|
273
284
|
}
|
|
@@ -1374,12 +1385,324 @@ function testCard(ocgcoreWrapper, ...ids) {
|
|
|
1374
1385
|
return logs;
|
|
1375
1386
|
}
|
|
1376
1387
|
|
|
1388
|
+
// src/advancors/slient-advancor.ts
|
|
1389
|
+
var SlientAdvancor = () => {
|
|
1390
|
+
return (msg) => {
|
|
1391
|
+
return msg.defaultResponse();
|
|
1392
|
+
};
|
|
1393
|
+
};
|
|
1394
|
+
|
|
1395
|
+
// src/advancors/static-advancor.ts
|
|
1396
|
+
var import_nfkit = require("nfkit");
|
|
1397
|
+
var StaticAdvancor = (items) => {
|
|
1398
|
+
const _items = (0, import_nfkit.makeArray)(items).slice();
|
|
1399
|
+
return () => _items.shift();
|
|
1400
|
+
};
|
|
1401
|
+
|
|
1402
|
+
// src/advancors/no-effect-advancor.ts
|
|
1403
|
+
var import_ygopro_msg_encode6 = require("ygopro-msg-encode");
|
|
1404
|
+
|
|
1405
|
+
// src/advancors/map-advancor.ts
|
|
1406
|
+
var MapAdvancorHandler = (msgClass, cb) => ({
|
|
1407
|
+
msgClass,
|
|
1408
|
+
cb
|
|
1409
|
+
});
|
|
1410
|
+
var MapAdvancor = (...handlers) => {
|
|
1411
|
+
const handlerMap = /* @__PURE__ */ new Map();
|
|
1412
|
+
for (const handleObj of handlers) {
|
|
1413
|
+
handlerMap.set(handleObj.msgClass, handleObj.cb);
|
|
1414
|
+
}
|
|
1415
|
+
return (msg) => {
|
|
1416
|
+
const cb = handlerMap.get(
|
|
1417
|
+
msg.constructor
|
|
1418
|
+
);
|
|
1419
|
+
if (cb != null) {
|
|
1420
|
+
const res = cb(msg);
|
|
1421
|
+
if (res != null) {
|
|
1422
|
+
return res;
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
return void 0;
|
|
1426
|
+
};
|
|
1427
|
+
};
|
|
1428
|
+
|
|
1429
|
+
// src/advancors/no-effect-advancor.ts
|
|
1430
|
+
var NoEffectAdvancor = () => MapAdvancor(
|
|
1431
|
+
MapAdvancorHandler(import_ygopro_msg_encode6.YGOProMsgSelectChain, (msg) => {
|
|
1432
|
+
if (msg.chains.length) {
|
|
1433
|
+
return;
|
|
1434
|
+
}
|
|
1435
|
+
return msg.prepareResponse(void 0);
|
|
1436
|
+
})
|
|
1437
|
+
);
|
|
1438
|
+
|
|
1439
|
+
// src/advancors/combined-advancor.ts
|
|
1440
|
+
var CombinedAdvancor = (...advancors) => {
|
|
1441
|
+
return (msg) => {
|
|
1442
|
+
for (const advancor of advancors) {
|
|
1443
|
+
const res = advancor(msg);
|
|
1444
|
+
if (res != null) {
|
|
1445
|
+
return res;
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
return void 0;
|
|
1449
|
+
};
|
|
1450
|
+
};
|
|
1451
|
+
|
|
1452
|
+
// src/advancors/limit-advancor.ts
|
|
1453
|
+
var LimitAdvancor = (a, limit = 1) => {
|
|
1454
|
+
let called = 0;
|
|
1455
|
+
return (msg) => {
|
|
1456
|
+
if (called >= limit) {
|
|
1457
|
+
return void 0;
|
|
1458
|
+
}
|
|
1459
|
+
const res = a(msg);
|
|
1460
|
+
if (res !== void 0) {
|
|
1461
|
+
called++;
|
|
1462
|
+
}
|
|
1463
|
+
return res;
|
|
1464
|
+
};
|
|
1465
|
+
};
|
|
1466
|
+
var OnceAdvancor = (a) => LimitAdvancor(a, 1);
|
|
1467
|
+
|
|
1468
|
+
// src/advancors/player-view-advancor.ts
|
|
1469
|
+
var PlayerViewAdvancor = (player, a) => (msg) => {
|
|
1470
|
+
if (msg.responsePlayer() === player) {
|
|
1471
|
+
return a(msg);
|
|
1472
|
+
}
|
|
1473
|
+
return void 0;
|
|
1474
|
+
};
|
|
1475
|
+
|
|
1476
|
+
// src/advancors/summon-place-advancor.ts
|
|
1477
|
+
var import_ygopro_msg_encode7 = require("ygopro-msg-encode");
|
|
1478
|
+
var SummonPlaceAdvancor = (placeAndPosition = {}) => MapAdvancor(
|
|
1479
|
+
MapAdvancorHandler(import_ygopro_msg_encode7.YGOProMsgSelectPlace, (msg) => {
|
|
1480
|
+
const places = msg.getSelectablePlaces().filter(
|
|
1481
|
+
(p) => (placeAndPosition.player == null || p.player === placeAndPosition.player) && (placeAndPosition.location == null || p.location === placeAndPosition.location) && (placeAndPosition.sequence == null || p.sequence === placeAndPosition.sequence)
|
|
1482
|
+
).slice(0, msg.count);
|
|
1483
|
+
return msg.prepareResponse(places);
|
|
1484
|
+
}),
|
|
1485
|
+
MapAdvancorHandler(import_ygopro_msg_encode7.YGOProMsgSelectPosition, (msg) => {
|
|
1486
|
+
if (placeAndPosition.position) {
|
|
1487
|
+
return msg.prepareResponse(placeAndPosition.position);
|
|
1488
|
+
}
|
|
1489
|
+
const possiblePositions = msg.positions;
|
|
1490
|
+
for (let i = 0; i < 8; i++) {
|
|
1491
|
+
const value = 1 << i;
|
|
1492
|
+
if ((possiblePositions & value) !== 0) {
|
|
1493
|
+
return msg.prepareResponse(value);
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
return void 0;
|
|
1497
|
+
})
|
|
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
|
+
|
|
1377
1699
|
// index.ts
|
|
1378
1700
|
if (typeof globalThis !== "undefined" && !globalThis.Buffer) {
|
|
1379
1701
|
globalThis.Buffer = import_buffer.Buffer;
|
|
1380
1702
|
}
|
|
1381
1703
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1382
1704
|
0 && (module.exports = {
|
|
1705
|
+
CombinedAdvancor,
|
|
1383
1706
|
DirCardReader,
|
|
1384
1707
|
DirReader,
|
|
1385
1708
|
DirScriptReader,
|
|
@@ -1387,17 +1710,27 @@ if (typeof globalThis !== "undefined" && !globalThis.Buffer) {
|
|
|
1387
1710
|
LEN_EMPTY,
|
|
1388
1711
|
LEN_FAIL,
|
|
1389
1712
|
LEN_HEADER,
|
|
1713
|
+
LimitAdvancor,
|
|
1390
1714
|
MESSAGE_BUFFER_SIZE,
|
|
1715
|
+
MapAdvancor,
|
|
1716
|
+
MapAdvancorHandler,
|
|
1391
1717
|
MapReader,
|
|
1392
1718
|
MapScriptReader,
|
|
1719
|
+
NoEffectAdvancor,
|
|
1393
1720
|
OcgcoreDuel,
|
|
1394
1721
|
OcgcoreDuelOptionFlag,
|
|
1395
1722
|
OcgcoreDuelRule,
|
|
1396
1723
|
OcgcoreMessageType,
|
|
1397
1724
|
OcgcoreWrapper,
|
|
1725
|
+
OnceAdvancor,
|
|
1726
|
+
PlayerViewAdvancor,
|
|
1398
1727
|
QUERY_BUFFER_SIZE,
|
|
1399
1728
|
REGISTRY_BUFFER_SIZE,
|
|
1729
|
+
SelectCardAdvancor,
|
|
1730
|
+
SlientAdvancor,
|
|
1400
1731
|
SqljsCardReader,
|
|
1732
|
+
StaticAdvancor,
|
|
1733
|
+
SummonPlaceAdvancor,
|
|
1401
1734
|
ZipReader,
|
|
1402
1735
|
ZipScriptReader,
|
|
1403
1736
|
_OcgcoreConstants,
|