feedback1 gaps: DESIGN §21.26, META, PLAYING and CHANGELOG for the three gaps
DESIGN §21.26 describes the 变形同构体 pairing list, the harmony mark in the bond views and the bot's band pick; the normative lines of §6.3, §6.6, §8.2 / §8.3 and the §21.11 note point at it. META documents the band pick and the harmony field, PLAYING explains both for players, and the CHANGELOG 0.1.1 section gets two 界面 lines and one 人机 line.
This commit is contained in:
1 parent
016fdb3804
commit
0fb1a17e7e
4 files changed
+32
-11
No files matched your search
+15
-5
@@ -367,7 +367,7 @@ Economy/shop/pool/merge/hand rules: exactly as research 00-INDEX §3–§4 (inco
|
||||
|
||||
### 6.3 Bonds & layers (bondsMeta.js)
|
||||
|
||||
- `count` = number of **distinct base chess** on the board carrying the bond (`BOARD`); `BOARD_AND_DECK` bonds also count the hand; 绝技 counts elites on board; 调和 adds +1 to each core bond count, etc. (research 02).
|
||||
- `count` = number of **distinct base chess** on the board carrying the bond (`BOARD`); `BOARD_AND_DECK` bonds also count the hand; 绝技 counts elites on board; 调和 adds +1 to each core bond count that has a real member on the board (the views mark such an entry `harmony: 1`, §21.26), etc. (research 02).
|
||||
- 变形同构体: an operator wearing it together with an item that has a `giveBondId` is a member of that bond — counted like any member (BOARD: on the board only; once per operator), in the battle, and in the client's member list (tagged 同构) and bond chips (§21.11).
|
||||
- `tier` from thresholds; `active = tier ≥ 1`.
|
||||
- `layers[bondId]` persist all match; gains come from garrisons/bands/items/choices/bond effects; IN_BATTLE gains are collected from `BattleResult.layerGains` at SETTLE (disabled in unite/boss/hidden).
|
||||
@@ -384,7 +384,7 @@ Per match: pick stage (weighted among the mode's `config.modes[m].stages`, weigh
|
||||
|
||||
### 6.6 AI players (bot.js)
|
||||
|
||||
Deterministic-ish heuristic player used for (a) AI teammates, (b) auto-play for disconnected humans (only auto-ready + auto-picks, not shopping, unless "AI 托管" is toggled), (c) tests. Strategy (§21.6): pick a band (weighted by starting LP); each prep: take offers, sell dead bench weight, fill the board, complete affordable merges, level on the curve, then buy only merge progress / lineup upgrades worth more than the refreshes their price would buy (shop odds of completing held pairs), freeze for an unaffordable third copy (坎诺特 keeps 5 funds back); build around a committed focus core bond (a teammate's main bond on its strip counts against it; bonds the mode switches off never) + a second bond; value dealers by DPS vs the round's DEF / RES (an attack on every enemy in range counts double — 阵法术师 / 轰击术师), with the range the unit is deployed with; place by the exposure model + rehearsal on the server's deploy map (no 深水区; a tactician's 援军 within `PlayerState.summonRange`; `g.move` judges legality); items by effect (META §1.5: 突变细胞 on the least valuable normal single below 6阶, a cell left in temp gets a hand slot made for it); 机变 bounties by expected payout − expected LP loss over the offered cards; resolve temp — on a human seat under AI 托管 never by destroying an item while a bench operator can be sold for the slot —; ready. A bot's whole prep — shop decisions and layout planning (`botPrepBeginSteps`, 25–70 ms late in a 4-bot match), the layout rehearsal and `botPrepEndSteps` — runs in wall-clock slices of `botSliceMs` (8 ms) per scheduler callback on a real host (step generators that yield between whole actions, never with a transient board; the same actions in the same order, so decisions are unchanged; at once in virtual time).
|
||||
Deterministic-ish heuristic player used for (a) AI teammates, (b) auto-play for disconnected humans (only auto-ready + auto-picks, not shopping, unless "AI 托管" is toggled), (c) tests. Strategy (§21.6): pick a band (weighted by starting LP; never one built around a bond the mode switches off — `gd.bandBondIds`, §21.26); each prep: take offers, sell dead bench weight, fill the board, complete affordable merges, level on the curve, then buy only merge progress / lineup upgrades worth more than the refreshes their price would buy (shop odds of completing held pairs), freeze for an unaffordable third copy (坎诺特 keeps 5 funds back); build around a committed focus core bond (a teammate's main bond on its strip counts against it; bonds the mode switches off never) + a second bond; value dealers by DPS vs the round's DEF / RES (an attack on every enemy in range counts double — 阵法术师 / 轰击术师), with the range the unit is deployed with; place by the exposure model + rehearsal on the server's deploy map (no 深水区; a tactician's 援军 within `PlayerState.summonRange`; `g.move` judges legality); items by effect (META §1.5: 突变细胞 on the least valuable normal single below 6阶, a cell left in temp gets a hand slot made for it); 机变 bounties by expected payout − expected LP loss over the offered cards; resolve temp — on a human seat under AI 托管 never by destroying an item while a bench operator can be sold for the slot —; ready. A bot's whole prep — shop decisions and layout planning (`botPrepBeginSteps`, 25–70 ms late in a 4-bot match), the layout rehearsal and `botPrepEndSteps` — runs in wall-clock slices of `botSliceMs` (8 ms) per scheduler callback on a real host (step generators that yield between whole actions, never with a transient board; the same actions in the same order, so decisions are unchanged; at once in virtual time).
|
||||
|
||||
---
|
||||
|
||||
@@ -415,7 +415,7 @@ Platform additions (implemented): `welcome.{resumed, version}`, `room.state.inMa
|
||||
### 8.2 Match
|
||||
C→S (all carry `rid`): `g.infoReady` · `g.band {bandId}` · `g.bandSkip` · `g.bandFocus {bandId?}` (the strategy highlighted in the draft screen — what a timed-out turn takes; absent / null clears it; `WRONG_PHASE` outside BAND_DRAFT, `ALREADY` after the pick, `BAD_TARGET` for a band not allowed; §18.2) · `g.buy {slot}` · `g.refresh` · `g.freeze` · `g.levelUp` · `g.sell {uid}` · `g.move {uid, to:{area:'board', row, col}|{area:'hand', idx}, dir?}` · `g.equip {itemUid, targetUid, replaceUid?}` (`replaceUid`: which equipped item a third one replaces, §6.2) · `g.art {itemUid, row, col, dir?}` (`dir` ∈ UP|RIGHT|DOWN|LEFT from the deploy wheel, §3; absent ⇒ `to.dir`, then RIGHT; `g.move` onto the piece's own tile re-orients it; board pieces in `m.private` / `m.field {prep:true}` carry `dir`) · `g.destroy {uid}` (hand / temp items only; equipped items are locked, §6.2) · `g.reward {idx}` · `g.choice {idx}` · `g.ready {ready}` · `g.emote {id}` · `g.watch {fieldId}` · `g.autoplay {on}` · `g.pause {on}` (solo battles only, §14 Solo pause) · `g.unitStats {seq?}` (ROUND_START / SP_DRAFT / PREP, else `WRONG_PHASE`; eliminated: `ELIMINATED`) → push `m.unitStats` (§18.5) · `g.leave`
|
||||
S→C:
|
||||
- `m.public` — full public state on every change (throttled ≤ 10/s): `{ phase, round, lastRound, deadline, serverNow, modeId, difficulty, stageId, factions, disabledBonds, bannedChess, bossId, hiddenBossId?, teamLp?, bossHp?:{hp,max}, overtimeAt? /* FA / HC: ms epoch the overtime drain starts, §4 */, paused /* solo pause, §14 */, draft?:{order,turn,picks,skipsLeft,turnDeadline,turnSeconds /* one turn's length, 0 untimed; deadline = turnDeadline (§18.2) */,untimed}, sp?:{family,cards /* bounty cards carry descRaw?, §20.6 */,turn,picks}, players:[{playerId, seat, name, isBot, connected, alive, lp, bandId, shopLevel, boardCount, ready, bonds:[{bondId,count,active,tier,layers}], fieldId, status, pendingLp? /* COMBAT / 联防 of a normal round: the LP the player's own battle will cost at settlement so far, min(lpCapPerRound, counted leaks) — in 联防 min(lpCapPerRound, uniteLeft) — omitted when 0 and in every other phase (§17.5 live LP) */, uniteLeft? /* 联防: the leaker's enemies still standing — not spawned yet + alive + counted leaks, uncapped, live (§20.6) */}] , fields:[{fieldId, kind, players:[playerId...]}] }`
|
||||
- `m.public` — full public state on every change (throttled ≤ 10/s): `{ phase, round, lastRound, deadline, serverNow, modeId, difficulty, stageId, factions, disabledBonds, bannedChess, bossId, hiddenBossId?, teamLp?, bossHp?:{hp,max}, overtimeAt? /* FA / HC: ms epoch the overtime drain starts, §4 */, paused /* solo pause, §14 */, draft?:{order,turn,picks,skipsLeft,turnDeadline,turnSeconds /* one turn's length, 0 untimed; deadline = turnDeadline (§18.2) */,untimed}, sp?:{family,cards /* bounty cards carry descRaw?, §20.6 */,turn,picks}, players:[{playerId, seat, name, isBot, connected, alive, lp, bandId, shopLevel, boardCount, ready, bonds:[{bondId,count,active,tier,layers,harmony? /* 调和's +1 is in count, §21.26 */}], fieldId, status, pendingLp? /* COMBAT / 联防 of a normal round: the LP the player's own battle will cost at settlement so far, min(lpCapPerRound, counted leaks) — in 联防 min(lpCapPerRound, uniteLeft) — omitted when 0 and in every other phase (§17.5 live LP) */, uniteLeft? /* 联防: the leaker's enemies still standing — not spawned yet + alive + counted leaks, uncapped, live (§20.6) */}] , fields:[{fieldId, kind, players:[playerId...]}] }`
|
||||
- `m.private` — the recipient's full PlayerState view (§6.2 minus server-only data) on every change.
|
||||
- `m.field` — field meta when watching starts: `{ fieldId, kind, rect, stageId, units: [UnitInfo] }` (the units on the field, knocked-out operators waiting to redeploy included — `Battle.fieldMeta`, §18.3)
|
||||
- NOTE: game time in `b.snap`/`b.ev` is carried as **`gt`** (the frame's `t` is the message type).
|
||||
@@ -438,7 +438,7 @@ S→C:
|
||||
temp: [ Piece | null ], // length 5
|
||||
board: [ Piece & { row, col, dir } ], // dir ∈ UP|RIGHT|DOWN|LEFT (§3; bench pieces carry none)
|
||||
deployCap, deployCount,
|
||||
bonds: [ { bondId, count, active, tier, layers, thresholds, countsHand } ], // sorted: active first, then layers desc
|
||||
bonds: [ { bondId, count, active, tier, layers, harmony? /* 调和's +1 is in count, §21.26 */, thresholds, countsHand } ], // sorted: active first, then layers desc
|
||||
effects: [ { id, name, desc, iconKind: 'band'|'choice'|'team'|'item'|'garrison', iconId, counter?, counterText? /* a bounty: 还剩 N 场作战, §20.6 */ } ],
|
||||
nextEnemies: [ { enemyKey, count, tag } ], // preview of the upcoming round's wave (after waves.js generation)
|
||||
stats: { dmgDealt, kills, leaks, gold, refreshes, merges } }
|
||||
@@ -1230,7 +1230,7 @@ Eighteen workstreams (WA–WR, each on its own branch from master 7f13473) were
|
||||
- **Seen**: with 变形同构体 (缪尔赛思's 特质 garrison_76 / band 变形者集群) and the matching item the wearer gets the bond's effect, but "那个盟约的人口数量没有把转职之后的干员算进去". **Partly real**: the count that activates the bond already included the wearer everywhere (`bondsMeta.pieceBonds` for the prep count, m.private / m.public, the battle input; `support.unitBonds` in the battle — checked on real matches for all 36 pairings). The client did not: the popup's member list and the wearer's card read only the records' bonds (在场 3/6 next to 成员 2/10, no chip).
|
||||
- **Official**: band 变形者集群 "与特定装备一同装备时装备者将视为特定盟约成员"; eff_acarm073 "携带者获得额外盟约(由另一件携带装备而定)"; the item's talent lists the 14 pairings; a member counts on the board only (BOARD) and once per operator.
|
||||
- **Now**: `gameLogic.grantedBonds` = the server's rule (a test pins the three together); the popup lists wearers tagged 同构, the card shows the granted bond as a dashed 同构 chip; a 同构 row opens the wearer's card with its item ids; a card without an own piece lists the carried items read-only under 装备. UnitInfo `items?` (sim `unitInfo`, `Match.prepFieldMeta`) carries an ally operator's item ids, so teammates' popups and cards show wearers too.
|
||||
- [ASSUMED], unchanged: operator talents that test "【拉特兰】/【卡西米尔】/【叙拉古】… 干员" read the record's bonds (kits tier1 内线 ammo pick, tier5 inFaction, tier6 hasBond, tokens.js 卡西米尔 sword) — no source says whether a converted operator counts for them; 调和's +1 raises 在场 for core bonds without a member row.
|
||||
- [ASSUMED], unchanged: operator talents that test "【拉特兰】/【卡西米尔】/【叙拉古】… 干员" read the record's bonds (kits tier1 内线 ammo pick, tier5 inFaction, tier6 hasBond, tokens.js 卡西米尔 sword) — no source says whether a converted operator counts for them; 调和's +1 raises 在场 for core bonds without a member row (explained since §21.26: 含调和 +1 and a 调和 row).
|
||||
- Tests: `test/ui/morph-bonds.test.js`, `test/ui/watch-bonds.test.js`, server-side locks in the match suite.
|
||||
|
||||
### 21.12 源石溶剂 is damage; 信仰搅拌机 S3 counters any damage (D1) — `sim/damage.js periodicDamage / isHpLoss / applyHpLoss`, `items/battle.js periodic_damage`, kits tier1 / 2 / 4 / 5, `content/enemies.js`, `bonds/addon/battle.js`, `choices.js`
|
||||
@@ -1404,3 +1404,13 @@ Not done (noted, no primary source or out of scope): whether 华法琳 S2's 流
|
||||
|
||||
- **The prep dispatcher's equipped items** (pointed out in PR #2, whose 突变细胞 rule is superseded by §21.1): step 5 iterated `holder.items` live while handlers move and destroy pieces — normal 博士投影 destroys itself at the round start (the splice skipped the next item on that holder), 突变细胞 transforms its holder (the next item ran with a holder that was gone). It now walks a snapshot of the owned chess and of each holder's items and runs an item only while it is still equipped on its still-owned holder; a piece gained or equipped meanwhile waits for the next dispatch (effectsMeta header, META §2.2). No shipped item has a second hook on those events, so play is unchanged; a synthetic spy handler pins the rule (`test/match/feedback1-dispatch-snapshot.test.js`).
|
||||
- **fetch-assets never shrinks the committed manifest by accident** (pointed out in PR #7, whose `data/assets.json`, regenerated on a machine where some downloads failed, was 42 audio entries short — all 42 still resolve upstream): a rebuilt manifest leaves out every entry whose files are missing on that machine. When it would lose an entry of the current `data/assets.json`, the run keeps the current file, prints the entries it would drop (also the report's `droppedEntries` / `manifestWritten`) and exits 1; `--allow-shrink` (or `--prune`) writes it (ASSETS.md; `test/fetch-assets-shrink.test.js`).
|
||||
|
||||
### 21.26 Gaps found while triaging GitHub issues #1 / #8 (v0.1.1)
|
||||
|
||||
Where: `ui/gameLogic.js morphPairings / HARMONY_BOND / harmonyMembers`, `ui/detailPanel.js MorphPairings / MorphGrantLine / ItemDetail / ChessDetail / BondChips`, `ui/bondStrip.js BondPopup / BondStrip`, `match/bondsMeta.js computeBonds / bondList`, `match/gamedata.js bandBondIds`, `match/bot.js botPickBand`, `public/dev/game-mock.js` (variants `funny` / `morph` / `harmony`). Three gaps the user decided to close in 0.1.1; no rule changes.
|
||||
|
||||
- **变形同构体 shows its pairings** (issue #1: players read the "转职球" as doing nothing). Its text says "具体对应关系可在模拟中查看本装备天赋栏", and no screen showed that 天赋栏. **Now** the item card (shop, reward, hand / temp: `ItemDetail`) has a 天赋 section: "搭配以下装备时,携带者视为对应盟约的成员:", then one line per bond in bonds.json order — 【bond】 and the items whose `giveBondId` is it (one name per item family, by tier): the 14 pairings of the official talent (character_table trap_1073_acarm073, "“炎国短刀”→【炎】盟约 …"; a test checks the two against each other), its "“维式重锤”系列装备" as the 5 hammers — 18 items, built from the same `giveBondId` the server counts with (`morphPairings`; `pieceBonds` / `grantedBonds`). A bond the mode never activates is struck through with 本局禁用 (`modeOffBonds`, §21.7; 标准: 拉特兰 阿戈尔 卡西米尔 奥术 突袭). On a wearer's card (its 装备 rows; also a teammate's unit and the card a 同构 row opens) the pairing it wears is highlighted — 生效中, or 已搭配 when that bond is off — and a wearer without one reads 暂未生效. A bond item's card and row say "与变形同构体一同装备时,携带者视为【X】成员" (`MorphGrantLine`). The 机密商店 cards have no detail view and keep the official text. Phones: the list keeps ≥ 9 px (px floors in `game-panels.css`).
|
||||
- **调和's +1 explained** (issue #1: "一些不考虑整备区的盟约计算人数时也会把整备区的干员算进去" — the +1 read as a miscount; §21.11 had left "调和's +1 raises 在场 for core bonds without a member row"). The rule is unchanged (§6.3; one +1 total, research 02 §2.1 [ASSUMED]). **Now** a bond state whose count holds the +1 carries `harmony: 1` (`computeBonds`) and both views send it — m.private `bonds[]` and m.public `players[].bonds[]` entries `{ …, harmony? }` (absent otherwise; not in the battle input, `bondSnapshot`) — so the client never re-derives the rule. The popup says 在场 n(含调和 +1) and a 调和 row heads its member list, naming the 调和 operators on that board (`harmonyMembers`: 缪尔赛思, Pith's 盟约·辅助干员; a tap opens the first one's card; with that board not on screen "调和已激活:核心盟约激活人数 +1") — for your own strip and a teammate's (§20.15: the entry from m.public, the operators from the field on screen). The strip disc's and the card chip's titles add (含调和 +1).
|
||||
- **Bots skip strategies built around a switched-off bond**: in 标准 the bot took 潘格尼尼 (【定制铳械】 an elite <拉特兰>), 克莱门莎 (<阿戈尔>) or 玛恩纳 (<卡西米尔>) in 5 of 200 solo and 23 of 800 co-op picks (seeds 1–200). `GameData.bandBondIds` reads a band's tie from its own data — the bond names in <…> of its text (the official note "在<X>部分干员缺席时体验可能不完整" among them; a bracketed item or enemy adds nothing) and the bond ids / bond pools of its blackboards (`bond`, `bond_id`; `pool` → choices.json `pools[pool].bond`, 潘格尼尼's pool_char_later) — nine bands are tied (杜遥夜 炎, 佩佩 / 娜仁图亚 萨尔贡, 哈洛德 维多利亚, 休露丝 谢拉格, 潘格尼尼 拉特兰, 克莱门莎 阿戈尔, 玛恩纳 卡西米尔, 贾维 叙拉古). `botPickBand` weighs a band tied to a bond of `gd.modeInactiveBonds` 0 — one rng draw per pick, the default band when every offered band is excluded: 0 of 200 and 0 of 800 in 标准, while the other modes keep exactly the earlier picks (绝境: 5 / 200, 23 / 800). A human may still pick those bands (open: a 本局禁用 mark on them in the strategy draft).
|
||||
- Normative lines rewritten with it: §6.3 (`harmony` in the views), §6.6 (the band pick), §8.2 / §8.3 (`bonds[]` entries `harmony?`), §21.11 (its 调和 note).
|
||||
- Tests: `test/ui/feedback1-gaps.test.js`, `test/match/feedback1-gaps.test.js`; opt-in `test/ui/feedback1-gaps.e2e.test.js` (`SP_E2E=1`; 1920×1080, 844×390, 756×366; `SP_E2E_OUT` moves the screenshots).
|
||||
Reference in new issue
Block a user