39 Commits

Author SHA1 Message Date
ebf2a0dc98 fix: N2H2V5独立分支用NeuralBotV5 - 新增NeuralBotV5类 + InitBots映射 + --n2h2v5参数 2026-07-18 11:20:14 +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
4263146487 fix: code review — 清理CardTracker死代码 + IsmctsBot未使用变量
CardTracker.BombsOutside: 删除13行注释+空循环(seenByRank从未填充)
IsmctsBot: 删除未使用的bombRanks变量
2026-07-12 22:51:48 +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
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
d520534b5b fix: InferType — ISMCTS模拟Type不再为None,所有牌型正确推演
根因: MakePlay/AddCandidate设Type=None,导致SimulateOneGame中
myPlay.Type=None, GetTipCard不匹配任何case→对手全员pass→评估失真

修复:
- 新增 InferType(): 根据牌数和面值分布推断牌型
  1张→DanZhang 2张→DuiZi 4同→ZhaDan 4+2→SiDai2
  4+3→SiDai3 3+2→SanDai2 ≥5→顺子/连对
- AddCandidate+MakePlay 均使用 InferType 替代 CardType1.None
- ISMCTS模拟中对手能正确识别我的出牌类型并跟牌

10局验证: FeiJi首次出现(2次), 全牌型:
  DanZhang 72 | DuiZi 47 | ShunZi 11 | SanDai2 10 | LianDui 5 | FeiJi 2 | ZhaDan 1
多牌比例: 51%
2026-07-07 14:32:13 +08:00
6299e4e580 feat: AddMultiCardLeads 补全 — 连对/飞机/飞机带对
新增枚举:
- 连对(LianDui): 提取对子 → 排序 → 找≥3连续段(如334455)
- 飞机(FeiJi): 提取三张 → 排序 → 找≥2连续段(如333444)
- 飞机带对(FeijiDai2): 连续三张 + 每组附带1对子

辅助方法: SortByGameNum/AddConsecutiveGroups/GetConsecutiveRuns

10局验证: LianDui 5次出现
完整牌型: DanZhang 76 | DuiZi 37 | ShunZi 17 | SanDai2 7 | LianDui 5 | SiDai3 1
(飞机需≥2连续三张,16张牌罕见但逻辑已就位)
2026-07-07 14:28:49 +08:00
2dd0bc3f78 feat: AddMultiCardLeads 补全 — 三带二/四带二/四带三
引擎支持(GetOutCard已验证): DanZhang/DuiZi/SanDai2/ShunZi/LianDui/
  FeiJi/ZhaDan/SiDai2/SiDai3/FeijiDai2

AddMultiCardLeads 新增:
- 三带二: 三张相同 + 附带手牌最小的2张
- 四带二: 四张相同 + 附带2张 (优先四带三)

10局验证: DuiZi 54 | DanZhang 53 | ShunZi 16 | SanDai2 13 | SiDai 2
单张比例: 100% → 38%
2026-07-07 14:22:48 +08:00
5547f75b5a fix: 多牌先手枚举 — 根除只出单张问题
根因: GetTipCard 在 GameNum≤0(新轮次)时只返回单张候选,
不包含对子/三张/顺子/炸弹等多牌先手方案。

修复:
- 新增 AddMultiCardLeads(): 新轮次枚举全部多牌先手
  - 对子 (GetMultiGroups:2) 三张 (3) 顺子(PokerLogic.GetShunZi) 炸弹(PokerLogic.GetPlayZhaDans)
- GetMultiGroups(): 统计同面值牌数,生成多牌候选
- 两阶段选择: 多牌候选优先,按牌数多少×胜率排序
- GetOutCard集成: 确保引擎收到正确牌型(DuiZi/ShunZi而非假DanZhang)

10局验证: DanZhang 59 | DuiZi 33 | ShunZi 16 | ZhaDan 1
多牌比例: 46% (之前0%)
2026-07-07 14:19:38 +08:00
3ef9d7f29e fix: GetOutCard 集成 — bot 出牌类型不再硬编码 DanZhang
根因: MakePlay 永远设 Type=DanZhang,bot 路径跳过 GetOutCard 校验,
导致多牌组合(对子/顺子等)被错误标为单张。

修复:
- MakePlay: Type=DanZhang → Type=None(占位,等引擎赋值)
- WaitWanJiaShuRu case4: bot 有Ids时通过 GetOutCard 获取正确牌型
- payCard.Pos 补设(GetOutCard 输出 Pos 默认为0)
- ISMCTS 日志: 按 Ids 为空判断 pass,而非 Type

现在游戏日志正确显示: type:DanZhang/type:None/type:DuiZi 等
2026-07-07 14:07:35 +08:00
4c21e5d8b5 fix: ISMCTS v2 — 包庄阈值校准 + 多牌组合Rollout + 防死循环
P0修复: 包庄严重高估
- 阈值 45%→60%(1000局数据校准)
- Rollout 对手从「最小单张」改为 PickBestTip(最大+多牌优先)
- 模拟对手更强 → P(win) 估计更准确

P2修复: 只出单张不组合
- 新增 PickBestTip(): 优先多牌组合(对子/顺子 > 单张)
- 同数量选最大的牌
- Rollout 模拟中所有玩家均受益

P1确认(虚警): 75 moves 异常局实为碾压局(高牌玩家清16张)
- 加 pass streak 检测:连续 2 pass 则强制最大出牌
2026-07-07 13:59:49 +08:00
4a3fbec057 test: 1000轮 ISMCTS 压测 + 完整分析报告
新增:
- hjha-console/Program.cs: --stress N 压测模式
  - 每局独立日志 stress_logs/round_NNNNN.txt
  - 每 50 局进度汇报 + 异常捕获
- docs/stress-test-report.md: 完整分析报告
  - P0: 包庄严重高估(5.2%成功) → 需校准阈值
  - P1: 75 moves 异常局 → 疑似死循环
  - P2: 只出单张不组合 → rollout 优化
  - P3: 性能瓶颈分析
- .gitignore: stress_logs/, analyze_stress.py

压测结果: 12.8min, 0 crashes, 1000/1000通过
2026-07-07 13:53:46 +08:00
d23e0b7616 fix: ISMCTS包庄决策——600次模拟估算P(win), 阈值45%
替换占位逻辑(大牌≥6张)为真正的蒙特卡洛评估:
- EstimateWinProbability(): 模拟N局完整对局, 统计我第一个出完的概率
- 阈值45%: 包庄收益翻倍, 略微倾斜于有利局势
- 日志: [ISMCTS posX] 包庄评估: P(win)=XX% → 包庄/不包

原理: 包庄不改变牌局流程(不像斗地主叫地主), 只翻倍输赢。
因此决策简化为 P(win|我的手牌) ≥ 阈值 → 包庄。
2026-07-07 13:29:36 +08:00
a75733e4ae feat: ISMCTS bot + full documentation
新增:
- PdkFriendServer/Logic/IsmctsBot.cs: ISMCTS蒙特卡洛搜索机器人
  - 800次模拟/决策,对手手牌从未知牌池随机采样
  - 包庄决策:大牌(≥J/Q/K/A/2)数量 ≥6 则包庄
  - winRate日志输出,决策透明
- docs/bot-architecture.md: 系统架构文档
- docs/bot-algorithms.md: A/B/C三条算法路径完整分析
- docs/ismcts-design.md: ISMCTS实现设计详案

切换:
- PdkGameMain.InitBots: PdkBot → IsmctsBot(默认ISMCTS)

验证:
- dotnet build 0 errors
- 多人对局完整运行:包庄→出牌→结算→test over
2026-07-07 13:27:00 +08:00
ec87d921a3 feat: PdkBot — 外挂式自动出牌机器人
架构:
- IPdkBot 接口:外挂接入点,与核心逻辑解耦
- PdkBotView:只传自己手牌+公开信息(MaxPlayCard/ShenYuCard/Rule)
  不暴露其他玩家手牌——模拟真人视角
- PdkBot:score-based 最优策略
  评分维度:直接获胜>>对手威胁>>牌效率>>炸弹保留>>先手权>>黑桃3

对接:
- PdkGameMain.BotMode=true 启用
- WaitWanJiaShuRu中BuildBotView→bot.DecidePlay/DecideBaoZhuang
- GameBaoZhuang解除WhoPlay=GetNextPos注释以支持逐人轮询
- SetFalseOperation加DeskGameDo null守卫

文件:
- PdkFriendServer/Logic/PdkBot.cs(核心机器人)
- PdkFriendServer/Logic/PdkGameMain.cs(BotMode+对接)
- hjha-console/Program.cs(main.BotMode=true启动)
2026-07-07 13:11:13 +08:00
025b8fc1e2 fix: Windows paths → ./gamepack/, empty Console.ReadLine guard
- SendPack(): C:\Users\Administrator\Desktop\temp\ → ./gamepack/
  (Path.Combine + Directory.CreateDirectory for cross-platform)
- WaitWanJiaShuRu(): add IsNullOrWhiteSpace + ss.Length checks
  before accessing ss[0]/ss[1] to prevent IndexOutOfRange on empty input
- .gitignore: add gamepack/ exclusion
2026-07-07 12:56:39 +08:00
7b6c031d44 feat: net10.0 Linux Console mode — zero Mono, 0 compile errors
Migrated from net48 (.NET Framework) to net10.0 (cross-platform):
- All 14 csproj: net48 → net10.0, WindowsDesktop SDK → Microsoft.NET.Sdk
- Excluded WinForms files (Form/**, DebugControl, GameControl, etc.)
- Excluded DB modules (GameDAL db/Sql/**, MrWu DB files)
- Excluded server runtime files (GameBase, GlobalSever managers, GameNetModule stubs)
- Added minimal stubs (GameDoStub.cs, NamespaceStubs.cs, ServerCoreStubs.cs)
- Created hjha-console entry project
- Fixed hardcoded Windows path → ./test/ directory
- Updated global.json to SDK 10.0.109

Console test mode: PdkGameMain(null).Test() → 发牌→包庄→打牌→结算
Verified: dotnet build 0 errors, dotnet run outputs game state machine
2026-07-07 12:47:59 +08:00