Skip to content

feat(tracker): 思泣/巧织技能适配 + 木马弱候选收敛修复#54

Merged
llsccm merged 3 commits into
devfrom
feat/siqi
Jul 24, 2026
Merged

feat(tracker): 思泣/巧织技能适配 + 木马弱候选收敛修复#54
llsccm merged 3 commits into
devfrom
feat/siqi

Conversation

@llsccm

@llsccm llsccm commented Jul 23, 2026

Copy link
Copy Markdown
Owner

概述

新增思泣(3543)/巧织(3544)技能对暗牌来源的推断适配,并修复适配期间暴露的木马(木牛流马 mark:700)弱候选与已知牌来源物化冲突。

改动

技能适配(527bbea)

  • 思泣 SiQi:弃牌区按红色牌反推来源实体候选,patch 移动事件的 sourceCards + combinationID
  • 巧织 QiaoZhi:展示→暗取→明弃三段差集反推暗取的手牌身份,落定为确定手牌(spellID:null,避免后续进木马时残留「标记(巧织)」描述)。
  • 配套隐藏标记/来源解析增强:createExternal 缺口补建后统一 confirmKnown;手牌 known 路径禁止消费 mark 占位等。

木马弱候选收敛修复(a0d5986)

场景:3 号位 141(明)+2 暗,暗置 1 张进木马形成弱候选;整手 [29,50,113] 完整进处理区、141 不在其中 → 141 必在木马。此前会 createExternal([50]) 并把真实手牌占位丢弃。

  • A(时序):新增 resolveHiddenMarkCandidatesFromFullHandReveal,在 resolveKnownMoveCards 之前对整手完整揭示做局部反向收敛——不在揭示 ID 里的候选明牌解到 mark,被挤出的匿名占位挤回来源手牌。
  • B(占位守恒)bindConfirmedMarkCardToMarkSpace 的 player-mark 占位回收改为挤回 sourceSeat 手牌,而非丢 outside(容器投影占位仍回 outside)。

诊断瘦身

  • SiQi 移除牌底端点诊断脚手架与 afterMove 二次对账(连带删 Room.moveCards 死钩子)。
  • QiaoZhi 删除纯诊断的 getAnonymousHandEntityIDs / getUnknownPlayerCards 与冗余状态字段。

测试

  • 新增 tests/tracker/trojanFullHandReveal.test.ts(木马整手揭示复现守卫)、tests/tracker/knownDiscardConfirm.test.ts
  • 全量 284 条 tracker 测试通过typecheck:tracker / lint / build 均清洁。

遗留

本轮为针对「整手完整揭示」触发的补丁;木马/mark 双重表示的结构性根因与更优方案(中心化守恒原语 / 收敛器增强)已记录在本地 plans/mark-space-and-trojan-convergence.md(gitignore,不入库),待后续单独立项。

🤖 Generated with Claude Code

Summary by CodeRabbit

  • 新功能
    • 新增“巧织”与“思泣”的移动事件处理:支持展示阶段校验、暗取候选推断与差集结算,并将结果可靠落到目标手牌。
  • 问题修复
    • 修复公共区场景下子区域/来源推断错误,避免手牌与暗置占位混淆;整手完整揭示时更准确地将弱候选收敛进木马容器,并提升公共区脏状态触发的视图刷新一致性;调整“思泣”相关弃牌补齐行为。
  • 测试
    • 新增/更新巧织、思泣、弃牌确认、整手揭示与视图脏刷新等覆盖用例。

llsccm and others added 2 commits July 24, 2026 01:17
木马(木牛流马 mark:700)弱候选与已知牌来源物化冲突修复:
- A(时序): 新增 resolveHiddenMarkCandidatesFromFullHandReveal,在
  resolveKnownMoveCards 之前对整手完整揭示做局部反向收敛——不在揭示 ID
  里的候选明牌解到 mark,被挤出的匿名占位挤回来源手牌,消除 createExternal
  与"明牌未找到可立即置换的手牌占位"告警。
- B(占位守恒): bindConfirmedMarkCardToMarkSpace 的 player-mark 占位回收
  改为挤回 sourceSeat 手牌而非丢 outside(容器投影仍回 outside)。
- 复现守卫: tests/tracker/trojanFullHandReveal.test.ts。

技能打磨:
- SiQi: 移除牌底端点诊断脚手架与 afterMove 二次对账(连带删 Room.moveCards
  死钩子),收敛为单条 debug 日志,功能推断不变。
- QiaoZhi: 删除纯诊断的 getAnonymousHandEntityIDs / anonymousHandEntityIDsBefore
  与 getUnknownPlayerCards,结算日志精简;差集反推逻辑不变。

全量 284 条 tracker 测试通过;typecheck/lint/build 清洁。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

技能移动事件装饰

Layer / File(s) Summary
巧织与思泣事件处理
src/tracker/skill/*, src/tracker/runtime/moveEventHandlers.ts, src/handler/spellEffects.js, tests/tracker/qiaoZhi.test.ts, tests/tracker/siQi.test.ts
新增巧织差集推断和思泣红牌来源装饰,注册对应技能事件,并移除旧的思泣法术副作用处理。

隐藏标记与已知牌收敛

Layer / File(s) Summary
隐藏标记候选收敛
src/tracker/roomMovement/hiddenMarks.ts, src/tracker/Room.ts, tests/tracker/trojanFullHandReveal.test.ts
新增身份物化、标记绑定和整手揭示处理,维护手牌/标记确认集合及匿名占位。
已知牌来源解析
src/tracker/roomMovement.ts, src/tracker/roomMovement/sources.ts, tests/tracker/knownDiscardConfirm.test.ts
调整来源区域推导、手牌候选过滤、缺口补建和 confirmKnown() 收口流程。

事件归一化与视图脏状态

Layer / File(s) Summary
公共区事件和渲染状态
src/tracker/MoveEventNormalizer.ts, src/tracker/Room.ts, tests/tracker/moveEventNormalizer.test.ts, tests/tracker/viewDirtyRender.test.ts
公共区事件不再填充手牌子区,公共区变更同步标记视图脏状态,并新增相关测试。

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MoveEventHandlers
  participant QiaoZhi
  participant SiQi
  participant Room
  MoveEventHandlers->>QiaoZhi: 分发 3544 移动事件
  QiaoZhi->>Room: 记录展示牌并结算差集
  MoveEventHandlers->>SiQi: 分发 3543 移动事件
  SiQi->>Room: 读取来源区红牌并注入 sourceCards
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确概括了思泣、巧织适配以及木马弱候选收敛修复,和本次变更主线一致。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/siqi

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (4)
src/tracker/MoveEventNormalizer.ts (1)

351-351: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

注释建议改为陈述式说明。

// subZone 在观看公共区时会被设置成 hand, 我觉得不太合理,改成了 undefined 为第一人称口语,建议改为客观说明变更原因(例如:观看公共区时不应默认推导为 hand,故公共区来源置为 undefined)。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tracker/MoveEventNormalizer.ts` at line 351, 将 MoveEventNormalizer.ts 中说明
subZone 的注释改为客观陈述,明确表达观看公共区时不应默认推导为 hand,因此公共区来源设置为 undefined;移除第一人称和口语化表述。
src/tracker/skill/QiaoZhi.ts (2)

33-39: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

建议将诊断性跳过日志降为 debug。

recordDisplayedCards/recordHiddenGain/settleHiddenGain 对所有正常跳过分支均使用 trackerLogger.info,而同 PR 的 SiQi.ts 使用 debug。3544 事件为高频入口,info 会显著增加日志噪声,建议诊断类日志统一用 debug

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tracker/skill/QiaoZhi.ts` around lines 33 - 39, 将 QiaoZhi.ts 中
recordDisplayedCards、recordHiddenGain 和 settleHiddenGain 的正常跳过分支日志从
trackerLogger.info 降为 trackerLogger.debug,保持现有日志内容及返回逻辑不变,统一与 SiQi.ts 的诊断日志级别。

15-21: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

提取共享 helper,消除 getRaw/getCount/hasPositiveID 重复。 两个新技能文件复制了与 src/tracker/runtime/moveEventHandlers.ts 相同的事件读取工具,建议抽到共享模块(如 src/tracker/skill/moveEventUtils.ts)统一导入,降低后续维护分叉风险。

  • src/tracker/skill/QiaoZhi.ts#L15-L21:移除本地 getRaw/getCount,改为从共享模块导入。
  • src/tracker/skill/SiQi.ts#L9-L19:移除本地 getRaw/getCount/hasPositiveID,改为从共享模块导入。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tracker/skill/QiaoZhi.ts` around lines 15 - 21, 将
src/tracker/runtime/moveEventHandlers.ts 中与事件读取相关的 getRaw、getCount、hasPositiveID
提取到共享模块 src/tracker/skill/moveEventUtils.ts,并统一导出。更新
src/tracker/skill/QiaoZhi.ts 第15-21行移除本地 getRaw/getCount,改为导入共享实现;更新
src/tracker/skill/SiQi.ts 第9-19行移除本地
getRaw/getCount/hasPositiveID,改为导入共享实现,确保现有调用行为不变。
src/tracker/roomMovement/hiddenMarks.ts (1)

984-992: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

占位回收筛选可与 bindConfirmedMarkCardToMarkSpace 保持一致(防御性)。

此处挑选被挤出的匿名占位仅判 isAnonymousCard(ph) && ph !== card,而 bindConfirmedMarkCardToMarkSpace 额外校验 subZone === 'mark'spellID === record.spellID。当前 record.placeholderCards 通常同 spellID,风险有限;但补齐同样的筛选可避免后续账本混入其它子区/spellID 占位时误回收。

♻️ 建议筛选
-        const placeholder = Array.from(record.placeholderCards ?? []).find(
-          (ph) => isAnonymousCard(ph) && ph !== card
-        )
+        const placeholder = Array.from(record.placeholderCards ?? []).find(
+          (ph) =>
+            isAnonymousCard(ph) &&
+            ph !== card &&
+            ph.location === 'player' &&
+            ph.subZone === 'mark' &&
+            Number(ph.spellID) === Number(record.spellID)
+        )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tracker/roomMovement/hiddenMarks.ts` around lines 984 - 992, 更新 hidden
mark 占位回收逻辑中 `record.placeholderCards.find` 的筛选条件,除 `isAnonymousCard(ph)` 且 `ph
!== card` 外,补充校验 `ph.subZone` 为 `mark` 且 `ph.spellID` 等于 `record.spellID`,使其与
`bindConfirmedMarkCardToMarkSpace` 的筛选保持一致。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/tracker/MoveEventNormalizer.ts`:
- Line 351: 将 MoveEventNormalizer.ts 中说明 subZone 的注释改为客观陈述,明确表达观看公共区时不应默认推导为
hand,因此公共区来源设置为 undefined;移除第一人称和口语化表述。

In `@src/tracker/roomMovement/hiddenMarks.ts`:
- Around line 984-992: 更新 hidden mark 占位回收逻辑中 `record.placeholderCards.find`
的筛选条件,除 `isAnonymousCard(ph)` 且 `ph !== card` 外,补充校验 `ph.subZone` 为 `mark` 且
`ph.spellID` 等于 `record.spellID`,使其与 `bindConfirmedMarkCardToMarkSpace` 的筛选保持一致。

In `@src/tracker/skill/QiaoZhi.ts`:
- Around line 33-39: 将 QiaoZhi.ts 中 recordDisplayedCards、recordHiddenGain 和
settleHiddenGain 的正常跳过分支日志从 trackerLogger.info 降为
trackerLogger.debug,保持现有日志内容及返回逻辑不变,统一与 SiQi.ts 的诊断日志级别。
- Around line 15-21: 将 src/tracker/runtime/moveEventHandlers.ts 中与事件读取相关的
getRaw、getCount、hasPositiveID 提取到共享模块
src/tracker/skill/moveEventUtils.ts,并统一导出。更新 src/tracker/skill/QiaoZhi.ts
第15-21行移除本地 getRaw/getCount,改为导入共享实现;更新 src/tracker/skill/SiQi.ts 第9-19行移除本地
getRaw/getCount/hasPositiveID,改为导入共享实现,确保现有调用行为不变。

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 13712cbf-854b-4a31-9e85-b7a66271b764

📥 Commits

Reviewing files that changed from the base of the PR and between d0f2c86 and a0d5986.

📒 Files selected for processing (17)
  • src/handler/PubGsCMoveCard.js
  • src/handler/spellEffects.js
  • src/tracker/MoveEventNormalizer.ts
  • src/tracker/Room.ts
  • src/tracker/roomMovement.ts
  • src/tracker/roomMovement/hiddenMarks.ts
  • src/tracker/roomMovement/sources.ts
  • src/tracker/runtime/moveEventHandlers.ts
  • src/tracker/skill/QiaoZhi.ts
  • src/tracker/skill/SiQi.ts
  • tests/tracker/knownDiscardConfirm.test.ts
  • tests/tracker/moveEventNormalizer.test.ts
  • tests/tracker/qiaoZhi.test.ts
  • tests/tracker/siQi.test.ts
  • tests/tracker/spellEffects.test.ts
  • tests/tracker/trojanFullHandReveal.test.ts
  • tests/tracker/viewDirtyRender.test.ts
💤 Files with no reviewable changes (1)
  • src/handler/spellEffects.js

- 抽出 getRaw/getCount/hasPositiveID 到 moveEventUtils
- 整手揭示回收占位对齐 mark/spellID 筛选
- 巧织正常跳过日志降为 debug;公共区 subZone 注释客观化

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/tracker/skill/moveEventUtils.ts`:
- Around line 7-9: Update getCount to normalize event.cardCount or
event.options?.cardCount as a finite, non-negative integer before returning it.
Reject or safely default invalid values such as NaN, infinity, and fractions,
while preserving zero for missing or invalid counts and the existing
non-negative behavior for valid integers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 321b7f91-d8e3-4213-a9c7-e1d48e136779

📥 Commits

Reviewing files that changed from the base of the PR and between a0d5986 and 63e3f03.

📒 Files selected for processing (6)
  • src/tracker/MoveEventNormalizer.ts
  • src/tracker/roomMovement/hiddenMarks.ts
  • src/tracker/runtime/moveEventHandlers.ts
  • src/tracker/skill/QiaoZhi.ts
  • src/tracker/skill/SiQi.ts
  • src/tracker/skill/moveEventUtils.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/tracker/MoveEventNormalizer.ts
  • src/tracker/skill/SiQi.ts
  • src/tracker/skill/QiaoZhi.ts
  • src/tracker/roomMovement/hiddenMarks.ts

Comment thread src/tracker/skill/moveEventUtils.ts
@llsccm
llsccm merged commit eb4e51b into dev Jul 24, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant