feedback7: merge fb7-dobermann — 教鞭 is the official three-choice (PR #353 by @Sukvii, the owner's decision), the Final Assault / Hidden Core pay a 战术特训 card's perfect coins (guarded by b.progress leaksBy), the bots put zero-range heavy guards on the road first (PR #339 by @IceCodeNew, placement only)
- Conflicts (the branch started atae22335c): spec.js / protocol.js b.progress (resolved from fb7-ui-backlog + leaksBy), gameLogic.js / game.js exports (device tips + normalizePersonalChoice), docs/PLAYING.md / design/network.md lines merged against the base, META.md (画卷 note + 教鞭), test/docs-consistency.test.js pin (both fields). - Grok review: MERGE AFTER FIXES — the HIGH (a forged boss result paid the cards) fixed on the branch (66a228c6), the META wording (1ab12763). - Golden: matches 10 (the 杜宾 bot picks and the guard placement); union: coop3-ABYSS-5 differs from HEAD only in ai_2's dmgDealt (1238011 → 1186269), no outcome change — HEAD's side had moved it, the new placement applies on that path. - Broad node --test 5623 (5621 pass, 0 fail, 2 skipped); lint 0 errors; typecheck; i18n strict clean.
This commit is contained in:
commit
2de2feee3c
57 files changed
+1339
-276
No files matched your search
+22
-3
@@ -104,7 +104,7 @@ function refreshPrivate() {
|
||||
const p = S.priv;
|
||||
p.deployCount = p.board.filter((x) => x.kind === 'chess').length;
|
||||
p.bonds = computeBonds(p);
|
||||
p.canReady = !p.temp.some(Boolean);
|
||||
p.canReady = !p.personalChoice && !p.temp.some(Boolean);
|
||||
const upg = [5, 8, 11, 12, 13];
|
||||
p.shop.maxLevel = 6;
|
||||
if (p.shop.upgradePrice == null) p.shop.upgradePrice = upg[p.shop.level - 1] ?? 0;
|
||||
@@ -181,7 +181,7 @@ function buildState() {
|
||||
].sort((a, b) => a.t - b.t);
|
||||
|
||||
const priv = {
|
||||
playerId: ME, seat: 0, alive: !VARIANTS.has('dead'), lp: 24, funds: 13, bandId: 'band_bldsk', ready: false, canReady: true,
|
||||
playerId: ME, seat: 0, alive: !VARIANTS.has('dead'), lp: 24, funds: 13, bandId: 'band_bldsk', ready: false, canReady: true, personalChoice: null,
|
||||
shop: { level, maxLevel: 6, upgradePrice: 9, refreshPrice: 1, freeRefreshes: 0, frozen: VARIANTS.has('frozen'), slots, rewardOffer: null },
|
||||
hand, temp, board, deployCap: 8, deployCount: 0, bonds: [],
|
||||
effects: [
|
||||
@@ -680,7 +680,16 @@ async function mockRequest(t, f = {}) {
|
||||
}
|
||||
pushPublic(); return {};
|
||||
}
|
||||
case 'g.art': { prepOnly(); const it = findPiece(f.itemUid); if (!it) fail('BAD_TARGET'); removeAt(it); toast('奇术已生效', 'success'); refreshPrivate(); return {}; }
|
||||
case 'g.art': {
|
||||
prepOnly(); const it = findPiece(f.itemUid); if (!it) fail('BAD_TARGET');
|
||||
if (it.piece.id === 'chess_item_6_03_m') {
|
||||
if (p.personalChoice) fail('BAD_TARGET');
|
||||
const cards = data.get('choices').cards.bounty.filter((c) => c.payout === 'perfect' && c.rounds < 90).slice(0, 3)
|
||||
.map((c) => ({ ...c, kind: 'bounty', id: c.effectId, descRaw: data.lookup('effects', c.effectId)?.descRaw }));
|
||||
p.personalChoice = { id: `mock.choice.${nextUid()}`, round: pub.round, sourceItemId: it.piece.id, cards };
|
||||
}
|
||||
removeAt(it); toast('奇术已生效', 'success'); refreshPrivate(); return {};
|
||||
}
|
||||
case 'g.reward': {
|
||||
if (!p.shop.rewardOffer) fail('WRONG_PHASE');
|
||||
const s = p.shop.rewardOffer.slots[f.idx]; if (!s) fail('BAD_TARGET');
|
||||
@@ -688,6 +697,15 @@ async function mockRequest(t, f = {}) {
|
||||
p.hand[idx] = chessPiece(data.lookup('chess', s.id)); p.shop.rewardOffer = null; refreshPrivate(); return {};
|
||||
}
|
||||
case 'g.choice': {
|
||||
if (f.choiceId !== undefined) {
|
||||
prepOnly();
|
||||
const choice = p.personalChoice;
|
||||
if (!choice || choice.id !== f.choiceId || choice.round !== pub.round || !choice.cards[f.idx]) fail('BAD_TARGET');
|
||||
const card = choice.cards[f.idx];
|
||||
p.effects.push({ id: choice.id, name: card.name, desc: card.descRaw || card.desc, iconKind: 'choice', iconId: card.id });
|
||||
p.personalChoice = null;
|
||||
refreshPrivate(); return {};
|
||||
}
|
||||
if (!pub.sp) fail('WRONG_PHASE');
|
||||
const taken = Object.values(pub.sp.picks).includes(f.idx);
|
||||
if (taken) fail('BAD_TARGET');
|
||||
@@ -695,6 +713,7 @@ async function mockRequest(t, f = {}) {
|
||||
}
|
||||
case 'g.ready': {
|
||||
if (pub.phase !== PHASE.PREP) fail('WRONG_PHASE');
|
||||
if (f.ready && p.personalChoice) fail('BAD_TARGET');
|
||||
if (f.ready && !p.canReady) fail('TEMP_NOT_EMPTY');
|
||||
p.ready = !!f.ready; refreshPrivate(); return {};
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user