7566fe99a1
feat(PX): 自训练v1.5 P0准备 — NHN模式 + 总分法胜率解析 + 评估管线
...
CB-01: Program.cs 加 --nhn 模式 [NEURAL,ISMCTS,NEURAL]
- 3人跑得快 N插花坐排列
- Rotations 数组补全为4种排列 (IIN/NII/INI/NHN)
- --nhn 参数: 不生成CSV, 直接评估
CB-02: 胜率解析统一总分法
- TrainingCollector 加 ScoreAccumulator/BotWins/BotGames 静态累加器
- GameOver 无条件调用 AccumulateScore (eval + 训练模式均记录)
- stress_summary.txt 输出 #BOT_SCORES: bot=wins/games,wr=XX%,score=YYY
- orchestrator eval 解析改用 #BOT_SCORES 格式, 正则回退逻辑移除
管线: orchestrator eval→stress_summary→总分法解析, 闭环可验证
2026-07-20 15:40:59 +08:00
e777aef687
fix(PX): 训练数据文件名加进程启动时间戳前缀,防止rsync覆盖旧文件
...
FlushGame 文件名从 game_00000.csv 改为 game_YYYYMMDD_HHMM_000000.csv。
_sessionPrefix 在类加载时固化,同一采集批次共享前缀,不同批次按启动时间区分。
2026-07-20 14:01:56 +08:00
ebf2a0dc98
fix: N2H2V5独立分支用NeuralBotV5 - 新增NeuralBotV5类 + InitBots映射 + --n2h2v5参数
2026-07-18 11:20:14 +08:00
aa4cbd0a3e
fix: backup before selfplay, never rmtree — crash-safe
...
rmtree(training_data) → mv to training_data_prev
训练成功后再清理backup, 崩了数据不丢
2026-07-13 11:51:17 +08:00
f66f56d0f8
feat: ISMCTS q-value as training label
...
C#: TrainingCollector新增q_value列, IsmctsBot传入winRate
CSV: reward→q_value, ISMCTS状态带真实评估值, Neural填0
Python: 优先取ISMCTS状态+评估值训练, 无q_value的Neural状态跳过
旧CSV格式(reward)自动fallback到Neural-only过滤
信号从'这局谁赢'改为'ISMCTS评估这步有多好'
2026-07-13 11:38:42 +08:00
dc17c0f464
feat: position rotation every 10 games in self-play
...
--mix-rotate: 每10局轮换bot排列
[ISMCTS,ISMCTS,NEURAL] → [NEURAL,ISMCTS,ISMCTS] → [ISMCTS,NEURAL,ISMCTS]
Neural 三个位置都练到, 数据分布平衡
orchestrator改用--mix-rotate替换--mix
2026-07-13 11:28:45 +08:00
4e6ad234da
feat: Neural-only training, experience replay, per-round eval
...
3个训练效率提升:
1. Neural filter: V训练只取player=2数据, 排除ISMCTS状态干扰
旧格式(无player列)自动fallback全量数据
2. 经验回放: 保留最近3轮数据混入当前轮训练, 扩大分布覆盖
存储到 paodekuai-trainer/data/replay_buffer.pkl
3. 每轮eval: 训练后跑200局--eval测胜率, 下降>10%自动回滚
回滚到 model_prev.pt, 防止坏模型污染下轮数据
2026-07-13 11:26:40 +08:00
98ab4414a4
feat: improve V-training loop — weight decay, cosine LR, early stop
...
- Adam weight_decay=1e-5 to prevent overfitting
- CosineAnnealingLR 0.001→1e-5 over 50 epochs
- Early stopping after 10 epochs without improvement
- Epochs: 20→50 max (with early stop typically fewer)
2026-07-13 11:24:42 +08:00
4c1b1c971c
feat: 20k局/轮无限训练 + scan_wins支持存档目录
2026-07-13 08:43:39 +08:00
22acc3b2ca
feat: CSV加player列+#RESULT汇总 — 训练中直接看胜率进化
2026-07-13 08:40:14 +08:00
15b9ccb22b
feat: --eval 评估模式 (ISMCTS/ISMCTS/NEURAL, 不生成CSV)
2026-07-13 08:38:18 +08:00
27d7e28236
fix: 训练编排器 — V训练从头开始 + ONNX外部数据文件复制
2026-07-13 08:14:05 +08:00
493da4216d
feat: --mix-ismcts 纯ISMCTS训练模式 + --bots 自定义bot组合 (Mac无ONNX时自动切换)
2026-07-13 03:51:52 +08:00
24d6d02a22
fix: macOS Console.SetOut Dispose顺序 — 先恢复再Close避免ObjectDisposedException
2026-07-13 03:48:54 +08:00
9d4e4a0479
fix: global.json add rollForward latestMajor for Mac SDK 10.0.301
2026-07-13 03:41:20 +08:00
58e12e2def
feat: 远程Mac worker支持 — SSH分发训练任务
...
parallel_train.py --remote ouyangqi@100.121 .6.90
→ SSH到Mac执行 dotnet run --mix N
→ scp拉取training_data回VPS
→ 自动merge到本地数据池
→ SSH失败自动回退本地worker
用法:
# 仅本地
python3 scripts/parallel_train.py --workers 3 --games 333
# 本地2 + Mac1
python3 scripts/parallel_train.py --workers 3 --games 333 --remote ouyangqi@100.121 .6.90
# 本地1 + Mac2
python3 scripts/parallel_train.py --workers 3 --games 333 --remote ouyangqi@100.121 .6.90
注: Mac需先 git pull 最新代码 + dotnet build
2026-07-13 03:29:23 +08:00
2b108c4d41
feat: 训练效率优化 — B:全bot记录 + A:并行调度
...
B: NeuralBot也调用TrainingCollector.Record
→ 3个bot全部记录(之前只有ISMCTS)
→ 9样本/局(之前6, +50%)
A: parallel_train.py 并行调度器
python3 scripts/parallel_train.py --workers 3 --games 333
→ 串行3个worker各跑333局 → 合并数据到training_data/
效率: 1000局 ≈ 12分钟, 9000样本
之前: 1000局 ≈ 12分钟, 6000样本
2026-07-13 03:25:51 +08:00
b619b84f2a
config: --mix改为2×ISMCTS+1×NeuralBot (训练评估模式)
2026-07-13 03:18:47 +08:00
e5e1f4818e
fix: V-learning 出牌率 0%→81% — MakePlay Type=None导致所有候选被当pass
...
根因: MakePlay(Type=CardType1.None)
→ play.Type==None 对所有候选为true
→ afterHand保持原样(未出牌)
→ 所有候选V值相同 → 始终选第一个(pass)
修复:
- play.Type→play.Ids.Length判断是否真pass
- EncodeAfterPlay更新ShenYuCard(出牌后剩余-1)
- EncodeAfterPlay设MaxPlayCard为出的牌
- isPass用Ids==null而非Type
效果: Play 117 Pass 28(81%出牌) vs ISMCTS -108/10局
2026-07-13 03:03:36 +08:00
f43e47b0a6
feat: V-learning架构 — 改Q→V
...
Q-learning问题: pass action Q值稳定偏高 → 永远pass
V-learning修复:
- 网络输出 14(Q-action)→1(V-state): P(win|state)
- NeuralBot: 对每个候选编码出牌后state → 选V值最高的
- pass和出牌都是候选, 公平竞争(不是固定action slot)
TrainingCollector:
- 新增 EncodeAfterPlay(view, tracker, afterHand, playedIds)
- EncodeState 支持 extraSeen 参数(模拟出牌时标记已见)
Python:
- train_v.py: V-learning训练器(load CSV→predict win/loss)
- network.py: OUTPUT_DIM=14→1
验证: 200局0错误, V-model loss 0.81→0.0001
需更多数据覆盖状态空间
2026-07-13 02:52:48 +08:00
89743cd511
feat: NeuralBot — ONNX模型驱动的Bot + 混合Bot训练架构
...
NeuralBot.cs:
- 加载ONNX模型,状态编码与Python trainer完全一致(13rank×4suit×7ch=364)
- ε-greedy探索(10%) + ONNX推理选Q值最高动作
- 多牌候选: 对子/三带二(优先带对子)/顺子/炸弹
PdkGameMain:
- BotTypes静态配置: ["NEURAL","NEURAL","ISMCTS"] = 2模型+1ISMCTS
- --mix参数: dotnet run -- --mix 100
hjha-console:
- --mix参数自动设置BotTypes并转调--stress
验证: 3局0错误, 1.3s/局, NeuralBot出牌正常
2026-07-13 02:20:44 +08:00
68e8c038f4
feat: ISMCTS 4项优化 — 模拟终止+候选剪枝+SanDai2带对子
...
A: 模拟截断 MinPlays评估
旧: 张数最少=赢(不知道手牌结构) → 4张散牌 vs 3张对子, 4张赢(错)
新: MinPlays最少=赢 → 散牌minPlays=4 vs 对子minPlays=2, 对子赢(对)
C: 候选剪枝 fastRate<0.15
低胜率候选直接丢弃(非pass), 节省模拟+排序时间
全剪枝时自动回退不剪枝
E: SanDai2/SiDai 优先带对子
旧: 带最小两张散牌
新: 优先找对子带, 找不到才带散牌(对子本身是一手牌)
注: B(预测引导采样)回退 — PredictOpponent在每局800次模拟中重复调
用导致1.6s/局, 在线性能不可接受
验证: 100局0错误 0.8s/局
2026-07-13 01:45:45 +08:00
c23b53adf9
feat: 智能SimulateToEnd — PickBestTip按跟牌/领牌区分策略
...
回退纯贪心: Count×10+rank → 总是出最大牌(跟牌时浪费高牌,领牌时不效率)
修复:
- 跟牌(isNewRound=false): 出刚好压制的最小牌,保留大牌用于后续压制
评分 = Count×1000 + rank(越小越好)
- 领牌(isNewRound=true): 优先多牌组合提高清牌效率
评分 = Count×100 - rank(越大越好,多牌优先,同类型出小rank)
效果(100局vs 30局V4折算):
ShunZi 76→102(+34%), DuiZi 224→236(+5%), ShunZi明显提升
SanDai2 92→72(回到V1基准线), 多牌比例24.1%
验证: 100局0错误 0.8s/局
2026-07-13 01:28:58 +08:00
30a7f875f8
fix: 预测加权按牌型区分压制条件 — 修复SanDai2误杀
...
根因: oppMaxRank仅代表「对手有单牌」,但用单牌概率惩罚对子/三带二
→ 三带二需要对手有3张同rank才能压制,不是1张
修复: 按牌型分别判断
- DanZhang: 用 MaxRank (单牌条件)
- DuiZi: 用 LikelyPairs (对手是否有更高对子)
- SanZhang/SanDai2: 用 LikelyTriples (对手是否有更高三张)
- ShunZi: 用 MaxStraightLength + MaxRank
- 其他: 默认 MaxRank
效果: SanDai2 52→75/30局 (+44%), 多牌比例 25.4%→26.1%
验证: 100局0错误 0.8s/局
2026-07-13 01:14:57 +08:00
73c8783276
feat: 对手牌型预测 — PredictOpponent + ISMCTS 候选加权
...
CardTracker:
- 新增 OpponentPrediction 类: RankProbabilities/MaxRank/BombProbability/LikelyPairs/LikelyTriples/MaxStraightLength
- 新增 PredictOpponent: 基于剩余rank计数+对手手牌数计算期望持有量
核心公式: expected = remainingCount × (oppNeed / totalUnknown)
推断: 对子(>=1.5期望)/三张(>=2.5)/炸弹概率/顺子长度/MaxRank
- Pass约束强化: 对手pass过某单张 → 降低MaxRank
IsmctsBot:
- 新增步骤5.7 对手牌型预测加权:
我的出牌rank > 对手MaxRank → +8-13%
我的出牌rank < 对手MaxRank → -5%
对手可能有炸弹 → 大牌型-3%
验证: 100局0错误 0.8s/局
2026-07-13 01:05:14 +08:00
1b1404f38e
feat: 确定性牌计数推理v2 — AbsoluteHandStrength + 包庄否决 + 混合策略修正
...
CardTracker:
- 新增 AbsoluteHandStrength: 综合评估手牌实力(rank控制/绝对最高牌/炸弹/效率/已知率)
- 用于包庄决策的安全检查
IsmctsBot:
- EstimateWinProbability: 混合策略回退为纯ISMCTS + 确定性否决
(混合加成导致虚假信心, v3验证0%胜率)
- 策略: detStrength<0.15 → 直接否决不包, 否则纯ISMCTS
- 阈值保持 v2 水平: minPlays≤3→0.50,≤4→0.60,≤5→0.65
验证: 100局0错误 0.8s/局 ENDGAME=983次 LOCK=3次
2026-07-13 00:59:48 +08:00
5cc2ae8bd0
fix: 确定性牌计数推理 — UnknownCount修复 + 绝对大牌判断 + EndgameSolver修正
...
CardTracker:
- UnknownCount: 52→48 - handSize - seenCount (修正底牌+手牌漏算)
- 新增 RemainingCount/GetUnknownPool: 精确剩余牌计数
- 新增 IsAbsolutelyHighest: 全牌型确定性无敌判断 (单张/对子/三张/炸弹/顺子/连对/飞机)
EndgameSolver:
- GeneratePool → 调用 tracker.GetUnknownPool (修复已见牌未排除bug)
IsmctsBot:
- 确定性无敌出牌加成: 无敌出牌 +15-25% win rate bonus
SOIsmctsBot:
- 同步 UnknownCount(hand) 调用
验证: 100局0错误, 0.8s/局, ENDGAME求解正常触发
2026-07-13 00:40:27 +08:00
180be25ffa
fix: code review — 修复4个问题
...
1. CardTracker.UnknownCount: 48→52 (硬编码修正)
2. IsmctsBot.GenerateDeck → 静态FullDeck池复用 (减少对象分配)
3. CardTracker: 删除3个死字段(_passStreak/_isNewRound/_bombCounts)
4. CardTracker.Update: 清理pass约束记录逻辑
验证: 100局0错误, 0.9s/局
2026-07-13 00:21:15 +08:00
7fdc45057c
feat: 领牌保留策略 — 有绝对最高牌(2)时出最小的
...
问题: 玩家1有2+3+9, 领牌时出了9而非3
→ ISMCTS看不见'保留9未来组对子'的两步深度
修复:
- 有2时领牌单张: rank≤6→+15%, 7-10→+5%, J-K→-5%, A→-10%
- 核心逻辑: 有2能随时夺回控制权→出最小的→保留中牌组未来组合
效果: 单张更聪明(51%但质量高), ShunZi 11.6%, SanDai2 9.1%
2026-07-13 00:11:33 +08:00
1a97ea3d21
fix: afterMin权重强化 — 结构优化信号对抗模拟噪声
...
问题: 如玩家1手牌可拆2个顺子(6步完成), 但ISMCTS选择了8张顺子(7步)
→ 根因: 打散惩罚仅-3%, 被ISMCTS±3.5%噪声淹没
修复:
- 结构改善bonus: 12%→25% (对抗模拟噪声)
- 多牌打散penalty: 固定-3%→比例-30% (严重惩罚)
- 单张打散penalty: 新增-10%(之前无惩罚)
- 打散比例 = (afterMin-beforeMin)/beforeMin
效果: SanDai2 6.5%→8.1%(+25%), DanZhang-1.4%, 多牌54%
2026-07-13 00:05:22 +08:00
b5b02db2e6
结论: 切回IsmctsBot — SO-ISMCTS实验总结
...
SO-ISMCTS v4 (引擎级rollout+全牌型):
- GetTipCard在isNewRound时只返单张 → rollout对手只出单张
- 补多牌枚举后仍无法达到IsmctsBot的53%多牌率
- 根因: MO-ISMCTS的独立世界树更适合不完全信息卡牌游戏
SO的优势(信息共享)在对手手牌随机化的场景下被稀释
IsmctsBot最终指标: 多牌53%, 1.0s/局, 全牌型
SOIsmctsBot保留为备选方案
2026-07-12 23:51:24 +08:00
6a267738df
fix: FastSim清牌效率优先 — 领牌出多牌+最小rank, 跟牌出最小压制
...
核心改动: 从'出最大的看谁能压'改为'出最省的清牌快'
领牌(新轮):
- 三张 > 对子 > 单张 (多牌优先)
- 始终用最小rank (保留大牌给跟牌阶段)
跟牌:
- 三张/对子: 找最小rank能压制的同类型
- 单张: 出最小的压制牌(保留大牌)
效果: 多牌29%→34% (+5%), 单张-4.4%, 0.7s/局
vs IsmctsBot: 34% vs 53%, 差距来自straight/飞机等复杂牌型在rollout中缺失
2026-07-12 23:41:50 +08:00
8b30caff1a
perf: FastSim rollout 支持对子 (DuiZi) — 模拟更真实
...
FastSim改进:
- 新轮次: 优先找最大对子 → 再出最大单张
- 跟牌: 对子跟牌→找≥2张同rank且大于对手
- 单张跟牌: 找最小可压牌
效果: 多牌29%, ShunZi 8.8%, DuiZi 19.0%, 0.8s/局
已知局限: 贪婪rollout低估清牌效率, 后续需全局序列优化
2026-07-12 23:31:11 +08:00
30a4d06b33
fix: SO-ISMCTS 多牌候选补全 — 恢复ShunZi/ZhaDan/SanZhang
...
BuildCandidates: 复用 IsmctsBot.AddMultiCardLeads 完整牌型枚举
- 对子/三张/顺子/炸弹/连对 → 与 IsmctsBot 完全一致
- 使用 PokerLogic.GetShunZi + PokerLogic.GetPlayZhaDans
效果:
- ShunZi 0%→13.8%
- DuiZi 正常 (21.8%)
- 速度 0.8s/局
- 仍需改进 FastSim rollout (仅模拟单张)
2026-07-12 23:28:40 +08:00
2af570c0b3
perf: SO-ISMCTS v2 — 静态牌池实现 1.0s/局 (8x提升)
...
SOIsmctsBot.cs 重写:
- 静态 FullDeck[52]: 52张牌只创建一次, 模拟时只交换ID数组
- 预生成300份对手手牌分布 (byte[] ID数组)
- FastSim核心全部用 byte/List<byte>, 零对象分配
- 8个候选→800次模拟=800×4个List.ToList (可忽略)
性能: 7.9s→1.0s/局 (8x)
触发: 298次SOv2决策, 2次LOCK
默认启用: InitBots改用SOIsmctsBot
vs IsmctsBot:
- SO 更快收敛(单树共享统计)
- SO 确定性预生成hand(无随机采样偏差)
- 速度相同(1.0s)
2026-07-12 23:24:13 +08:00
bce5e10cf2
feat: SO-ISMCTS 备选方案 (非默认)
...
SOIsmctsBot.cs (新文件, 284行):
- 单树共享统计: SONode 累积所有候选的胜/负
- 200次检查收敛: winRate>90% → 提前终止
- 整合 HandOptimizer/CardTracker/EndgameSolver/LockDetector
性能问题 (当前不启用):
- 每次模拟重新生成对手手牌(48张TCardInfoPdkF) → 5-8x慢
- 优化方向: 对象池缓存+批量determinization
- 作为备选bot保留, InitBots仍用 IsmctsBot
2026-07-12 23:14:52 +08:00
df048f6266
feat: EndgameSolver — 终局精确求解替代ISMCTS采样
...
EndgameSolver.cs (新文件):
- 触发条件: 手牌≤5张 + 未知牌≤15张
- 枚举100种对手手牌分布 → 每分布贪心模拟到底 (深度限制30)
- 比 ISMCTS 更精确: 确定性模拟 vs 随机rollout
- 结果: 8/10局触发, 每局5-15次, 速度快(<50ms)
修复: candidates[1]越界
2026-07-12 23:06:32 +08:00
76e4133f58
feat: afterMin牌效率加权 — 出牌后手牌结构改善→加分
...
- beforeMin = 当前手牌最小步数
- afterMin < beforeMin → +12% × improvement率
- afterMin > beforeMin 且多牌 → -3% (打散手牌惩罚)
- 效果: 单张-1.2%, 三带二+0.9%, 飞机×3, 锁手+2次
2026-07-12 22:56:27 +08:00
4263146487
fix: code review — 清理CardTracker死代码 + IsmctsBot未使用变量
...
CardTracker.BombsOutside: 删除13行注释+空循环(seenByRank从未填充)
IsmctsBot: 删除未使用的bombRanks变量
2026-07-12 22:51:48 +08:00
cb33dcac6c
feat: LockDetector — 残局锁手必胜序列检测
...
LockDetector.cs (新文件, 170行):
- BFS搜索: 手牌≤8张时寻找无人能压制的出牌序列
- 硬锁: 每步绝对无人可挡→跳过ISMCTS,直接走必胜路径
- 支持5种牌型: 炸弹/对子/三张/三带二/顺子/单张
- 利用CardTracker.CanAnyoneBeat()判断压制可能性
- 优先大牌型(炸弹>顺子>三带二>对子>单张)
IsmctsBot集成:
- DecidePlay开头: hand≤8→调用LockDetector
- 发现锁手→跳过ISMCTS模拟,直接出牌(Console打LOG)
- Type=CardType1.None交给引擎GetOutCard重新算
生效条件: 残局+CardTracker累积足够已知牌信息+手牌有压制力
2026-07-12 22:40:49 +08:00
e67b06caa3
feat: CardTracker — 出牌记录+对手手牌推断+炸弹检测
...
CardTracker.cs (新文件, 400行):
- 48位bitset追踪已出牌(按ID)
- 对手pass约束记录: pass对子9→该对手无对子≥9
- BombsOutside(): 外面还剩几个炸弹
- BombRanks(): 可能藏炸弹的rank列表
- CanAnyoneBeat(play): 判断是否可能被压制
- SampleOpponentHands(): 约束采样替代随机分配
- 支持6种牌型的压制判断: 单张/对子/炸弹/顺子/连对/飞机
IsmctsBot.cs 整合:
- CardTracker实例,每次DecidePlay/DecideBaoZhuang调用Update()
- 炸弹感知加权: 外面没炸弹→我方炸弹+25%, 快赢时+15%
- 外面有炸弹且快赢→保守出牌(-5%多牌分)
- SimulateToEnd改用约束采样(回退随机补齐)
2026-07-12 22:36:22 +08:00
2f3b62e835
feat: 最小步数规划 + 自适应模拟 + 快速初筛
...
HandOptimizer.cs (新文件):
- DP 搜索手牌最优拆分, 计算最少出牌次数
- 支持全部牌型: 单张/对子/三张/三带二/顺子/连对/飞机/炸弹/四带二/四带三/飞机带对
- Analyze() 返回最优分组详情
- PlayEfficiency() 评估单次出牌的牌效率
IsmctsBot.cs 改进:
- 包庄决策加入 MinPlays 分析, 手牌散(≥7步)直接不包, 手牌好(≤3步)阈值降至50%
- 自适应模拟: 3张→2000, 4-6→1500, 7-10→1200, 11-13→1000, ≥14→800
- 快速初筛: 40次模拟定位好候选, 胜率>30%才追加模拟
- 多牌候选选择逻辑改为 top90% 阈值(之前无脑选多牌)
- 出牌时计算剩余手牌 MinPlays 辅助候选评估
- 简化 multiCount 追踪(改为 Any(c=>c.isMulti))
压测: 50局 0错误, avg 0.9s/局
2026-07-12 22:26:29 +08:00
8de64cc6ae
fix: 压测日志接入 ISMCTS stdout (sims/winRate) 到每局文件
2026-07-07 16:04:35 +08:00
00f33182ab
chore: ignore bot-package zip artifacts
2026-07-07 15:36:03 +08:00
13fe07ea11
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
2026-07-07 14:56:43 +08:00
aa30bfac29
tune: 包庄阈值 60%→70% + 多牌加权 +10%/张
...
包庄: 100局校准 60%阈值→30%成功率 → 提至70%(更保守)
多牌: 加 MultiBonusPerCard=0.10 加权,但实际效果有限——
两阶段选择已经无条件优先多牌。53%比例接近16张手牌
结构的天然上限(约一半牌可组组合,其余为散牌)
10局验证: DanZhang 88|DuiZi 61|ShunZi 19|SanDai2 10|LianDui 3|SiDai3 2
2026-07-07 14:51:44 +08:00
750e36462e
test: 100局v3压测报告
...
100/100 clean, 0 errors, 1.7min (1.0s/局)
牌型分布 (1523次出牌):
DanZhang 716 (47%)| DuiZi 504 (33%)| ShunZi 151 (10%)| SanDai2 82 (5%)
LianDui 41 (3%) | ZhaDan 18 (1%) | FeiJi 7 (.5%) | SiDai3 4 (.3%)
多牌比例: 53%
包庄: 18/300 (6%), 成功率 3/10=30% (阈值60%仍偏高)
稳定性: min 4 moves, max 57 moves (无异常局)
对比v2(1000局): 单张100%→47%, 多牌0%→53%
2026-07-07 14:47:27 +08:00
b39e28411b
refactor: 修复3个 🟡 问题 — 合并模拟方法/移除死参数/缓存GetMultiGroups
...
1. SimulateWin+SimulateOneGame → SimulateToEnd(nullable firstPlay)
减少 ~80行重复代码, 包庄/出牌共享同一模拟引擎
2. 移除 unknownCount 死参数 (SimulateOneGame 从未使用)
3. GetMultiGroups(hand,2) 只调一次 — 对子+连对共享 pairs 变量
文件: IsmctsBot.cs 583行 → 331行 (-43%)
2026-07-07 14:43:13 +08:00
ce2a4c98ef
review: code review + 3 critical fixes + 文档更新
...
Code Review 发现 (docs/code-review.md):
🔴 InferType 三元两边相同(无意义) → 重写,加 LianDui/FeiJi 分支
🔴 PdkBotView { get; init; } → { get; set; } (.NET 4.8 兼容)
🔴 PdkBot.DecideBaoZhuang ≤10永远false → bigCards≥6
文档更新 (docs/pdk-bot.md):
+ 5. 牌型全覆盖表(引擎+Bot枚举覆盖10种牌型)
+ 6. 双环境兼容指南(net48/n10 差异+集成步骤)
+ 附牌策略说明(引擎允许任意牌做挂件)
2026-07-07 14:39:50 +08:00
54d9f3add3
compat: switch expression → ternary for .NET 4.8 双兼容
...
IsmctsBot.cs:539: C#8 switch expression → C#7.3 ternary
num switch {1=>14,2=>16,_=>num} → num==1?14:num==2?16:num
bot代码(.NET 4.8)兼容性清单:
✅ LINQ (GroupBy/OrderBy/SelectMany) — 原生
✅ string 插值 $"..." — C#6
✅ ?./?? — C#6
✅ ValueTuple — 需 NuGet System.ValueTuple (net48)
✅ 已移除 switch expression — 唯一 C#8 特性
net48 项目集成只需3步:
1. 复制 PdkBot.cs + IsmctsBot.cs → PdkFriendServer/Logic/
2. csproj: <PackageReference Include="System.ValueTuple" Version="4.5.0"/>
3. WaitWanJiaShuRu 加入 BotMode 分支(同 net10.0 逻辑)
2026-07-07 14:36:13 +08:00