Skip to content

fix: 手气卡回牌堆匿名化与斗地主先手误设#48

Merged
llsccm merged 4 commits into
devfrom
codex/fix-mulligan-anonymize-doudizhu-firsthand
Jul 21, 2026
Merged

fix: 手气卡回牌堆匿名化与斗地主先手误设#48
llsccm merged 4 commits into
devfrom
codex/fix-mulligan-anonymize-doudizhu-firsthand

Conversation

@llsccm

@llsccm llsccm commented Jul 21, 2026

Copy link
Copy Markdown
Owner

摘要

  • 手气卡回牌堆时真正匿名化正 ID 槽,避免后续暗摸得到正 ID 独占暗手
  • 斗地主不再把叫分回包 Type 44 误当作最终地主/先手结果

变更说明

1. 手气卡回牌堆真正匿名化

根因:resetKnownToUnknown 只把 isKnown=false 写回牌堆,实体仍保留正 ID。后续未知摸牌会把该实体 bind 成正 ID 独占暗手,导致 discardKnown 物化目标只剩匿名槽时第二张解析失败。

修复:

  • 新增 Room.anonymizeLocatedIdentity:拆掉 cardIndex、身份回到 unlocatedIdentities、实体换负 ID
  • CardCounter.releaseLocatedIdentityToUnknown 同步计数桶
  • 更新/补充手气卡相关回归

2. 斗地主先手

CGsRoleSpellOptRep Type 44 是叫分操作回包,不是最终地主结果;原先用其 SeatID 调用 setTrackerFirstHand 会误设先手。现已移除该路径;Type 45 为系统播报地主结果但当前协议侧无法可靠取地主座位,仅作注释占位。

验证

  • pnpm exec vitest run tests/tracker/trackerController.test.ts tests/tracker/handCountObservation.test.ts tests/tracker/anonymousPileSpike.test.ts(45 passed)
  • Prettier check 通过

提交

  1. fix(tracker): 手气卡回牌堆真正匿名化
  2. fix(doudizhu): 不再用叫分结果误设先手

Summary by CodeRabbit

  • 功能改进

    • 明牌回到牌堆时会自动匿名化,避免后续暗摸错误继承原有身份。
    • 匿名卡牌将正确回归未知状态,并保持牌堆与身份记录一致。
    • 增强卡牌身份重置与状态追踪,支持更稳定的重复操作处理。
  • 问题修复

    • 修复部分牌局中已知牌回牌堆后仍可能以正 ID 暗牌出现的问题。
    • 调整叫分结果处理,避免错误设置首手信息。

llsccm added 2 commits July 22, 2026 03:02
resetKnownToUnknown 仅 isKnown=false 会在牌堆留下正 ID 未知槽,
后续暗摸会原样绑成正 ID 独占暗手并破坏 discardKnown 物化。
Type 44 只是叫分操作回包,不是最终地主结果;误用其 SeatID 设置先手。
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@llsccm, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 37 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c3c90008-a65e-47fe-b213-b0508feed496

📥 Commits

Reviewing files that changed from the base of the PR and between a45e565 and a5b93ce.

📒 Files selected for processing (2)
  • src/tracker/Room.ts
  • tests/tracker/roleSpellOptRep.test.ts
📝 Walkthrough

Walkthrough

本次变更新增已定位牌身份匿名化和未知状态回收流程,接入明牌回牌堆逻辑并补充暗摸验证;同时移除叫分结果处理中基于 SeatID 的首手设置。

Changes

已定位牌身份匿名化

Layer / File(s) Summary
未知状态回收
src/tracker/CardCounter.ts
新增 releaseLocatedIdentityToUnknown,将已定位身份、卡牌缓存和索引迁回 UNKNOWN 状态。
Room 身份匿名化
src/tracker/Room.ts
新增 anonymizeLocatedIdentity,解除正 ID 映射、分配匿名 ID、重置卡牌状态并记录变更事件。
回牌堆流程与验证
src/tracker/roomMovement.ts, tests/tracker/trackerController.test.ts
明牌回牌堆时先执行身份匿名化,并验证后续暗摸不会得到正 ID 暗手。

手气卡结果处理

Layer / File(s) Summary
结果类型分支调整
src/handler/CGsRoleSpellOptRep.js
handleResultType 不再读取 SeatIDType === 44 不再设置首手。

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant moveKnownCardsForContext
  participant Room
  participant CardCounter
  participant TrackerTest
  moveKnownCardsForContext->>Room: anonymizeLocatedIdentity(card)
  Room->>CardCounter: releaseLocatedIdentityToUnknown(card, previousCardID)
  CardCounter-->>Room: 更新 UNKNOWN 状态
  Room-->>moveKnownCardsForContext: 返回 previousCardID
  moveKnownCardsForContext->>TrackerTest: 验证负 ID 匿名牌
  TrackerTest->>TrackerTest: 执行暗摸并检查未知状态
Loading

Possibly related PRs

  • llsccm/tracker#45:同样涉及 RoomCardCounter 和牌移动流程中的已定位身份匿名化与回退。
  • llsccm/tracker#21:同样调整 moveKnownCardsForContext 中已知牌与匿名实体的处理。
  • llsccm/tracker#37:同样修改 handleResultTypeType === 44SeatID 的处理。
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题简洁且准确概括了本次修复的两项核心变更:手气卡回牌堆匿名化和斗地主先手误设。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fix-mulligan-anonymize-doudizhu-firsthand

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.

Type 44/45 不再调用 setTrackerFirstHand,更新 roleSpellOptRep 回归。

@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

🧹 Nitpick comments (1)
src/tracker/Room.ts (1)

521-530: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

建议用 setLocationCandidates() 替代直接赋值 locationCandidates,避免 owner 字段滞留旧值。

card.locationCandidates = [] 绕过了 setLocationCandidates()(代码库中清空候选的既有写法,参见本文件 materializeExistingIdentityAtTargetexisting.setLocationCandidates([], 'materialize:interop:known'))。此时 card.location 还未被重置(card.reset() 是调用方在这之后才执行的),若不经过 setLocationCandidates/syncOwnerFromSeatscard.owner 会暂时保留旧座位,card.seats getter 在 locationCandidates 为空时会回退到该旧 owner,而不是真正清空。当前唯一调用点因为紧跟 card.reset() 且不在 resolveConstraints() 循环内(resolveTouchedSeatsnull)而没有暴露问题,但作为新增的公共 Room 方法,建议收紧写法以避免未来复用时出现隐蔽的座位不一致。

♻️ 建议的修改
-    card.locationCandidates = []
+    card.setLocationCandidates([], reason)
🤖 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/Room.ts` around lines 521 - 530, 在 Room 中处理匿名实体 ID 分配的代码里,将直接赋值
card.locationCandidates = [] 改为调用
card.setLocationCandidates,并传入表示清空候选位置的现有上下文标识。确保该流程同步清理 owner,避免 card.seats 在
location 尚未重置时回退到旧座位。
🤖 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/handler/CGsRoleSpellOptRep.js`:
- Around line 17-18: Update the Type 44 regression test in roleSpellOptRep to
assert that setTrackerFirstHand is not called, reflecting the removed side
effect, and rename the test to describe the new behavior.

---

Nitpick comments:
In `@src/tracker/Room.ts`:
- Around line 521-530: 在 Room 中处理匿名实体 ID 分配的代码里,将直接赋值 card.locationCandidates =
[] 改为调用 card.setLocationCandidates,并传入表示清空候选位置的现有上下文标识。确保该流程同步清理 owner,避免
card.seats 在 location 尚未重置时回退到旧座位。
🪄 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: d4c0dbfc-f0cd-4d72-92fa-b65f4490b69a

📥 Commits

Reviewing files that changed from the base of the PR and between dcc6bbf and a45e565.

📒 Files selected for processing (5)
  • src/handler/CGsRoleSpellOptRep.js
  • src/tracker/CardCounter.ts
  • src/tracker/Room.ts
  • src/tracker/roomMovement.ts
  • tests/tracker/trackerController.test.ts

Comment thread src/handler/CGsRoleSpellOptRep.js
直接清空 locationCandidates 不会同步 owner,seats 会回退旧座位。
@llsccm
llsccm merged commit dadadda into dev Jul 21, 2026
3 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