chore: 清理冗余 + 文档更新至v3.1 + 打包清单

清理:
  - 删除 C:\Users\... Windows残留路径
  - analyze_stress.py → docs/
  - .gitignore 覆盖 stress_* runtime产物

文档更新:
  - pdk-bot.md: 包庄阈值45%→70%、RolloutPolicy描述、选牌策略
  - code-review.md: 7/7 全部清零
  - PACKAGE.md: 新建打包清单(代码+集成+文档+net48步骤+压测记录)

bot 文件总览:
  核心: PdkBot.cs(194行) + IsmctsBot.cs(331行) = 525行
  文档: pdk-bot.md + code-review.md + stress-test-report.md + PACKAGE.md
This commit is contained in:
2026-07-07 14:56:43 +08:00
parent aa30bfac29
commit 13fe07ea11
3 changed files with 73 additions and 23 deletions

49
docs/PACKAGE.md Normal file
View File

@ -0,0 +1,49 @@
# PdkBot 打包清单
## 核心代码2 文件525 行)
```
PdkFriendServer/Logic/PdkBot.cs IPdkBot 接口 + PdkBotView + 启发式基线
PdkFriendServer/Logic/IsmctsBot.cs ISMCTS 蒙特卡洛搜索(默认,推荐)
```
## 引擎集成点(已有修改,无需额外文件)
```
PdkFriendServer/Logic/PdkGameMain.cs BotMode 开关、BuildBotView、WaitWanJiaShuRu
hjha-console/Program.cs main.BotMode = true 入口 + --stress N 模式
```
## 文档
```
docs/pdk-bot.md 架构、算法、引擎整合、双兼容、压测报告
docs/code-review.md 7 项 review 发现 + 修复记录(已清零)
docs/stress-test-report.md 1000 局首次压测分析
docs/analyze_stress.py 压测日志分析脚本
```
## .NET 4.8 集成步骤
1. 复制 `PdkBot.cs` + `IsmctsBot.cs``PdkFriendServer/Logic/`
2. `PdkFriendServer.csproj` 加:
```xml
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<LangVersion>8.0</LangVersion>
```
3. `PdkGameMain.cs` 中复制 `BotMode`/`_bots`/`BuildBotView`/`InitBots` 成员和 `WaitWanJiaShuRu` 的 bot 分支
## 当前默认配置
- Bot: IsmctsBot (800 sims)
- 包庄阈值: 70%(成功率 57%
- 多牌加权: +10%/张
- 牌型覆盖: 10 种(全)
## 压测记录
| 版本 | 局数 | 单张 | 多牌 | 包庄成功率 | 提交 |
|------|------|------|------|-----------|------|
| v1 (启发式) | 1000 | 100% | 0% | 5.2% | - |
| v3.0 (ISMCTS) | 100 | 47% | 53% | 30% | 750e364 |
| v3.1 (阈值70%) | 100 | 44% | 56% | 57% | aa30bfa |

View File

@ -1,24 +1,18 @@
# PdkBot Code Review
## 发现汇总
**状态: ✅ 全部清零7/7**
### 🔴 Critical
| # | 文件 | 行 | 问题 | 影响 |
|---|------|-----|------|------|
| 1 | IsmctsBot.cs | 421 | `InferType` 三元表达式两边相同 `... ? SanDai2 : SanDai2` | 无实际分支 |
| 2 | IsmctsBot.cs | 422 | `InferType` 不识别 LianDui/FeiJi全归为 ShunZi | 模拟中牌型不准 |
| 3 | PdkBotView | 17-38 | `{ get; init; }` 是 C#9 语法 | .NET 4.8 不兼容 |
| # | 文件 | 问题 | 状态 | 修复 |
|---|------|------|------|------|
| 1 | IsmctsBot.cs:421 | `InferType` 三元表达式两边相同 | ✅ | 重写,加 LianDui/FeiJi 分支 |
| 2 | IsmctsBot.cs:422 | `InferType` 不识别 LianDui/FeiJi | ✅ | ShunZi/LianDui/FeiJi 各自分支 |
| 3 | PdkBotView:17 | `{ get; init; }` C#9→.NET 4.8 不兼容 | ✅ | → `{ get; set; }` |
| 4 | IsmctsBot.cs | `SimulateWin`/`SimulateOneGame` 80% 重复 | ✅ | 合并为 `SimulateToEnd(firstPlay?)` |
| 5 | IsmctsBot.cs:173 | `unknownCount` 死参数 | ✅ | 移除 |
| 6 | PdkBot.cs:62 | `DecideBaoZhuang``≤10`永远false | ✅ | → 大牌计数 ≥6 |
| 7 | IsmctsBot.cs:363 | `GetMultiGroups(hand,2)` 调两次 | ✅ | `pairs` 变量复用 |
### 🟡 Warning
| # | 文件 | 行 | 问题 | 影响 |
|---|------|-----|------|------|
| 4 | IsmctsBot.cs | 54-133, 215-307 | `SimulateWin``SimulateOneGame` 80% 重复 | 维护成本高 |
| 5 | IsmctsBot.cs | 173 | `unknownCount` 参数传入 SimulateOneGame 但从未使用 | 死参数 |
| 6 | PdkBot.cs | 62 | `DecideBaoZhuang``MyHand.Length <= 10`16张永远false | 包庄永远不触发 |
| 7 | IsmctsBot.cs | 363 | `GetMultiGroups(hand,2)` 被调两次 | 微性能浪费 |
### 🟢 OK
- `GenerateDeck()` 每次模拟调用 — 可缓存但 8000 次 × 52 元素 = 可接受
- `Pass()` 方法在两处重复 — 设计选择(两个 bot 独立)
- 三带二附带牌策略 — 已验证引擎允许任意牌做挂件
- `PickBestTip` null safety — tips 非空已外层保证
**代码规模:**
- IsmctsBot.cs: 331 行(原始 583 行,-43%
- PdkBot.cs: 194 行
- 总计: 525 行

View File

@ -114,17 +114,24 @@ DecidePlay(view):
return 胜率最高的方案
```
**RolloutPolicy模拟策略** `GetTipCard` 取第一个方案最小牌快速推进对局不需要最优——大量采样后统计收敛
**RolloutPolicy模拟策略** `PickBestTip` 选最优方案优先多牌组合 + 最大牌模拟更强的对手行为大量采样后 ISMCTS 胜率统计收敛
#### 包庄决策
```
DecideBaoZhuang(view):
模拟 600 局完整对局 → 统计我第一个出完的概率 P(win)
P(win) ≥ 45% → 包庄
P(win) ≥ 70% → 包庄
```
**为什么 45% 而不是 50%** 包庄是零和博弈中的多方决策你不包但别人包了你也要扣双倍阈值略微向攻方倾斜以弥补防守的机会成本
**阈值校准历程:** 45%v1)→ 60%v2成功率 30%)→ **70%v3.1,成功率 57%**100 局压测验证70% 阈值下包庄成功率翻倍
#### 选牌策略
两阶段选择
1. ISMCTS 评估所有候选胜率
2. 多牌组合 +10%/张加权 优先出对子/顺子/三带二等
3. 多牌 单张 无条件优先多牌
#### 性能