From 183b8c12b6f4da76beb0269282d7faf7eaae2521 Mon Sep 17 00:00:00 2001 From: sganggs Date: Wed, 7 Oct 2026 02:11:27 +0800 Subject: [PATCH] =?UTF-8?q?feedback5=20CB4:=20=E9=B8=AD=E7=88=B5's=20?= =?UTF-8?q?=E2=80=9C=E7=A5=9E=E7=A7=98=E9=A1=BE=E5=AE=A2=E2=80=9D=20swappi?= =?UTF-8?q?ng=20two=20enemies=20of=20one=20wave=20(two=20ducks=20included)?= =?UTF-8?q?=20is=20the=20official=200-2=20per=20wave=20=E2=80=94=20pinned,?= =?UTF-8?q?=20no=20change=20(community=20report=20of=202026-10-06,=20item?= =?UTF-8?q?=2035)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PRTS 下半/PRTS盟约记录 鸭爵 备注 「每回合将有0~2名敌人被替换为上述敌人之一」. 1000 real waves (m._normalOpts, solo and co-op, rounds 5-12): 0 / 1 / 2 swaps 388 / 312 / 300, never more; two of the same kind in 81 of the 300 2-swap waves. Golden unchanged. Tests: test/sim/feedback5-cb4-pins.test.js (+1). Docs: DESIGN §25.18.8. --- docs/history/0.2.0.md | 15 ++++++++++++++- test/sim/feedback5-cb4-pins.test.js | 27 ++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/docs/history/0.2.0.md b/docs/history/0.2.0.md index 993cde7e..a6464654 100644 --- a/docs/history/0.2.0.md +++ b/docs/history/0.2.0.md @@ -28,7 +28,7 @@ model quirks (PR #211) → §25.13; the community reports of 2026-10-06 (the 孤 bounty burned to death by the 活性源石, 枯朽之种 paying a bounty) → §25.14; the second batch of community reports of 2026-10-06, stream CB4 (enemies, bosses, waves, movement: the 突袭 landing on the 临时整备区 row and the other half of the 联防 map, a silenced 萨卡兹枯朽战士's death pollution, 萨卡兹穿刺手's speed after a stun and its first hit, 自制投石机 blocked on the 排气格栅; the briefing types' -7–9 waves, 新硎's 断刃 and a freed prisoner in 联防 already answered, …) → §25.18. +7–9 waves, 新硎's 断刃, a freed prisoner in 联防 and 鸭爵's two swaps in one wave already answered, …) → §25.18. Decisions of the owner: 2026-10-04 — the server stays on plain `node:http` + `ws`, no web framework (§25.1); 2026-10-05 — the 补位 plan (§25.3); the 自选编队 rules, the collab operators out of the pool, ISW-A refused (§25.4); @@ -1192,3 +1192,16 @@ The real ones are fixed, one commit each with its golden scenarios named; the re instead, every other ranged enemy still attacks its hidden blocker; the first two fail on the parent). Docs: docs/SIM.md. +#### 25.18.8 「鸭爵策略的悬赏现在有时候会一波出现多只,比如多只鸭子」 (item 35): the official 0–2 swaps per wave — no change + +- **Checked**: 鸭爵's “神秘顾客” (`round_start_all_player_change_enemy_2`: min 0, max 2, from round 5, the late part of the + wave — minweight 0.6 / maxweight 0.99) swaps 0–2 ground enemies of each player's wave, each into one of 鸭爵, 高普尼克, + 流泪小子, 圆仔 at random (bands/meta.js duckReplace, once per player per battle — no second handler). 1000 real waves + (`m._normalOpts`, solo and co-op, rounds 5–12): 0 swaps 388, 1 swap 312, 2 swaps 300, never more; the two of a 2-swap + wave were the same kind in 81 of 300 (≈ 1 wave in 12 with two ducks or two of another kind). A pair leader field holds + each player's 0–2 on its own half, and 联防 re-enters every leaker's leaked swaps (both as before). +- **Official**: PRTS 卫戍协议:盟约 下半/PRTS盟约记录 鸭爵 备注 「每回合将有0~2名敌人被替换为上述敌人之一」 — two ducks in one + wave is the official rule. +- Golden: unchanged. Pinned: `test/sim/feedback5-cb4-pins.test.js` (≤ 2 per wave, 0 / 1 / 2 and two of a kind all occur, + 1 fund each). + diff --git a/test/sim/feedback5-cb4-pins.test.js b/test/sim/feedback5-cb4-pins.test.js index e962ff4e..4bf82942 100644 --- a/test/sim/feedback5-cb4-pins.test.js +++ b/test/sim/feedback5-cb4-pins.test.js @@ -5,6 +5,9 @@ // constData maxLevelCnt 15 / specialEnemyNum 3 / enemyTypeIdentifierToFillRandom 1): each briefing type owns 3 of the // 15 round slots, SPECIAL (特异) the other 6, shuffled — R14 (leader) and R15 (hidden core) take slots too, so the 13 // normal rounds hold 7–9 type waves, at most 3 per type; +// item 35 「鸭爵策略的悬赏现在有时候会一波出现多只,比如多只鸭子」 — PRTS 下半/PRTS盟约记录 鸭爵 备注 「每回合将有0~2名敌人被 +// 替换为上述敌人之一」: each player's wave gets 0–2 swaps (bands/meta.js duckReplace), each one of the four at random, so +// two ducks in one wave is official (≈ 1 wave in 12 here); never more than 2 per player's wave; // item 57 「囚犯敌人的解放状态联防时不应继承」 — a leaked prisoner re-enters 联防 as a new spawn (unite.js planUnite → // waves.js buildUniteWave: its key and spawn mods only), confined again (archetypes.js prisoner spawn); the freed look // the report saw was 普通 / 老练囚犯's red clip set drawn from the gate, fixed with the prisoners' forms (§25.14.1). @@ -17,7 +20,7 @@ import { GameData } from '../../server/match/gamedata.js'; import { setupMatchWaves, buildUniteWave } from '../../server/match/waves.js'; import { planUnite } from '../../server/match/unite.js'; import { createRng } from '../../server/sim/rng.js'; -import { DATA } from '../match/harness.js'; +import { DATA, makeMatch } from '../match/harness.js'; test('item 6: the three briefing types fill 7–9 of the 13 normal waves (险境 / 绝境 / 终极), at most 3 each; the rest are SPECIAL', () => { for (const modeId of ['mode_multi_normal', 'mode_single_hard', 'mode_multi_abyss']) { @@ -74,3 +77,25 @@ test('item 57: a prisoner freed in its own combat leaks and re-enters 联防 con assert.equal(q.stats.attacks, 4, 'at its 4th attack in 联防 (confinement.times), as in a fresh spawn'); checkInvariants(u.b); }); + +test('item 35: the 鸭爵 strategy swaps 0–2 enemies of each player\'s wave, each one of its four at random (two ducks in one wave included), never more', () => { + const hist = [0, 0, 0]; + let twoSame = 0; + for (const seed of [31, 32]) { + const h = makeMatch({ mode: 'coop', difficulty: 'NORMAL', seed, fake: true }).start(); + h.toPrep(6, { band: 'band_ducklord' }); + for (const ps of h.m.alivePlayers()) { + for (let k = 0; k < 40; k++) { + const ducks = h.m._normalOpts(ps).spawns.filter((x) => x.tag === 'duck'); + assert.ok(ducks.length <= 2, `${ducks.length} swaps in one wave`); + hist[ducks.length]++; + if (ducks.length === 2 && ducks[0].enemyKey === ducks[1].enemyKey) twoSame++; + for (const d of ducks) assert.deepEqual(d.bounty, { coins: 1, ownerPlayerId: ps.playerId }); + } + } + h.m.dispose(); + } + assert.ok(hist.every((n) => n > 0), `0, 1 and 2 swaps all occur: ${hist}`); + assert.ok(twoSame > 0, 'two of the same kind (e.g. two ducks) in one wave occurs'); +}); +