feedback1 WA: Lappland counts her own first refresh; Mutation Cell is not consumed

Player reports after 0.1.0, #1 and #4.

#1 拉普兰德 (garrison_123, SERVER_GAIN_BOND_LAYER_BY_REFRESH_CNT) checked the
player's refresh count of the round, so a copy bought after the round's first
manual refresh never stacked that round. Players report the official
behaviour: the first refresh after acquiring her also stacks. Each copy now
counts the manual refreshes it witnessed this round (board or hand) through a
per-piece round counter (PlayerState.pieceRoundCount, ctx.incPieceCounter); an
elite merged this round keeps the highest count of its copies [ASSUMED]. The
"本回合每刷新过1次" multiplier traits keep the player's count.

#4 突变细胞 destroyed itself after one transformation. Official text never
says 销毁 (every consumable's does), PRTS notes "原干员销毁,获得一名高一阶的随机
初始干员", and players re-inject the cell every round. The built-in now replaces
the carrier with a random normal operator one tier higher (max 6) and returns
the carrier's equipment, the cell included, to the hand
(transformChess returnItems); the content override is gone. The item card
shows the rule (items.json note, build-data ITEM_RULES); bots inject their
least valuable single normal operator below tier 6 (bot.js cellTarget).
This commit is contained in:
sganggs committed 2026-10-03 01:47:52 +08:00
1 parent 7f134737ce
commit f8e35d5055
17 files changed
+514 -54

No files matched your search

+29 -1
View File
@@ -35,7 +35,9 @@
// order as the one-shot functions (runSteps), hence the same rng draws and decisions.
// The summon cards of the placed operators (赫默's 医疗探机, 伺夜's 狼群 …; user playtest #6) are placed after
// them on the best remaining tiles, 凯瑟琳's 支援装置 next to the best operator no device faces yet, facing it.
// 5. equip items on the strongest deployed damage dealers (consume-on-equip items / Arts only with a handler)
// 5. equip items on the strongest deployed damage dealers (consume-on-equip items / Arts only with a handler);
// 突变细胞 (it comes back after every transformation) on the least valuable single normal operator below 6阶 —
// never an elite or one of a merge pair (cellTarget)
// 6. resolve the temp slots, keep one hand slot free, then Ready.
// Placement quality (tools/matchrun sweeps, research-faithful waves): the planner beats random layouts by ≈ 8 points
// of kill rate and rehearsal adds ≈ 5 more; see docs/META.md §1.5.
@@ -1159,6 +1161,27 @@ function* placeTokensSteps(m, ps) {
}
}
/** 突变细胞 (buff char_chess_transformation_equip): after the battle its carrier becomes a random operator one tier higher. */
const isMutationCell = (gd, itemId) => { const rec = gd.item(itemId); return !!(rec && Array.isArray(rec.buffs) && rec.buffs.some((b) => b && b.key === 'char_chess_transformation_equip')); };
/**
* Whom the bot injects with 突变细胞 (after the battle the carrier is replaced by a random NORMAL operator one tier
* higher and the cell comes back — builtinMeta char_chess_transformation_equip): its least valuable normal operator
* below 6阶 with a free equip slot — never an elite or one of a merge pair (both would be lost), nobody already carrying
* a cell. null: the cell waits in the hand.
*/
export function cellTarget(m, ps, ctx = context(m, ps)) {
const gd = m.gd;
const cands = ps.allChess().filter((p) => !gd.isGolden(p.id) && gd.tierOf(p.id) < 6 && (p.items || []).length < gd.equipPerChess
&& !(p.items || []).some((it) => isMutationCell(gd, it.id)) && ps.countCopies(gd.baseIdOf(p.id)) < 2);
let best = null, bv = Infinity;
for (const p of cands) {
const v = pieceValue(m, ps, p, ctx);
if (v < bv) { bv = v; best = p; }
}
return best;
}
function equipItems(m, ps) {
const gd = m.gd;
const ctx = context(m, ps);
@@ -1168,6 +1191,11 @@ function equipItems(m, ps) {
const item = [...ps.hand, ...ps.temp].find((p) => p && p.kind === 'item' && canUseItem(m, ps, p) && !tried.has(p.uid));
if (!item) break;
tried.add(item.uid);
if (isMutationCell(gd, item.id)) {
const target = cellTarget(m, ps, ctx);
if (target) tryDo(() => ps.equip(item.uid, target.uid));
continue;
}
const rec = gd.item(item.id);
if (rec && rec.itemType === 'MAGIC') {
const board = [...ps.board.entries()].filter(([, p]) => p.kind === 'chess');