diff --git a/PdkFriendServer/Logic/CardTracker.cs b/PdkFriendServer/Logic/CardTracker.cs index dbca7c6e..4948fd79 100644 --- a/PdkFriendServer/Logic/CardTracker.cs +++ b/PdkFriendServer/Logic/CardTracker.cs @@ -242,6 +242,63 @@ namespace PdkFriendServer.Logic return false; } + /// + /// 确定性手牌强度:基于绝对牌计数评估手牌实力,0.0-1.0。 + /// 核心思想:我的手牌 + 已见牌 = 对手的牌池完全确定, + /// 可以精确计算哪些 rank 已被我控制、哪些出牌无敌。 + /// 用于修正 ISMCTS 模拟噪声。 + /// + public double AbsoluteHandStrength(TCardInfoPdkF[] myHand) + { + if (myHand.Length == 0) return 1.0; + + double score = 0.0; + + // 1. Rank 绝对控制率:我持有该 rank 所有剩余牌的百分比 + int controlledRanks = 0; + int[] ranks = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16 }; + foreach (int r in ranks) + { + int remaining = RemainingCount(r, myHand); + int myCount = myHand.Count(c => c.GameState == 1 && c.GameNum == r); + if (remaining == 0 && myCount > 0) + { + // 我持有该 rank 所有剩余牌 → 绝对控制 + controlledRanks++; + if (myCount >= 3) controlledRanks++; // 三张以上价值更高 + } + } + score += controlledRanks * 0.04; // 每个控制 rank +4% + + // 2. 绝对最高牌:持有 ♠2 或所有2 + int myTwos = myHand.Count(c => c.GameState == 1 && c.GameNum == 16); + int remainingTwos = RemainingCount(16, myHand); + if (remainingTwos == 0 && myTwos > 0) + { + score += myTwos * 0.06; // 每张独占 2 +6% + } + + // 3. 持有的炸弹数 + var byRank = myHand.Where(c => c.GameState == 1) + .GroupBy(c => c.GameNum) + .Where(g => g.Count() >= 4); + int myBombs = byRank.Count(); + score += myBombs * 0.08; // 每个炸弹 +8% + + // 4. 手牌效率(通过 HandOptimizer 间接) + int minPlays = HandOptimizer.MinPlays(myHand); + int handSize = myHand.Count(c => c.GameState == 1); + double efficiency = (double)(handSize - minPlays) + / Math.Max(handSize, 1); + score += efficiency * 0.15; // 效率贡献最多 15% + + // 5. 已知牌越多 → 确定性权重越高 + double seenRatio = _seenCardIds.Count / (double)Math.Max(48 - handSize, 1); + score += seenRatio * 0.10; // 已知牌占比 +10% + + return Math.Min(score, 1.0); + } + /// 在外面可能存在的炸弹数(按 rank 计) public int BombsOutside(TCardInfoPdkF[] myHand) { diff --git a/PdkFriendServer/Logic/IsmctsBot.cs b/PdkFriendServer/Logic/IsmctsBot.cs index cfb294bd..7042bc5c 100644 --- a/PdkFriendServer/Logic/IsmctsBot.cs +++ b/PdkFriendServer/Logic/IsmctsBot.cs @@ -68,6 +68,11 @@ namespace PdkFriendServer.Logic private double EstimateWinProbability(PdkBotView view) { + // 确定性安全检查:手牌极弱 → 直接否定包庄 + double detStrength = _tracker.AbsoluteHandStrength(view.MyHand); + if (detStrength < 0.15) return 0.0; + + // ISMCTS 模拟(确定性只做否决,不混入加成以避免虚假信心) int sims = Math.Min(_simulations, 600); int wins = 0; for (int s = 0; s < sims; s++) diff --git a/exe/PdkFriendServer/PdkFriendServer.dll b/exe/PdkFriendServer/PdkFriendServer.dll index cc3e6ec3..de535739 100644 Binary files a/exe/PdkFriendServer/PdkFriendServer.dll and b/exe/PdkFriendServer/PdkFriendServer.dll differ diff --git a/exe/PdkFriendServer/PdkFriendServer.pdb b/exe/PdkFriendServer/PdkFriendServer.pdb index 1daf6035..06491c6c 100644 Binary files a/exe/PdkFriendServer/PdkFriendServer.pdb and b/exe/PdkFriendServer/PdkFriendServer.pdb differ diff --git a/exe/hjha-console/PdkFriendServer.dll b/exe/hjha-console/PdkFriendServer.dll index cc3e6ec3..de535739 100644 Binary files a/exe/hjha-console/PdkFriendServer.dll and b/exe/hjha-console/PdkFriendServer.dll differ diff --git a/exe/hjha-console/PdkFriendServer.pdb b/exe/hjha-console/PdkFriendServer.pdb index 1daf6035..06491c6c 100644 Binary files a/exe/hjha-console/PdkFriendServer.pdb and b/exe/hjha-console/PdkFriendServer.pdb differ diff --git a/exe/hjha-console/hjha-console.dll b/exe/hjha-console/hjha-console.dll index 8b9b480c..b38bea20 100644 Binary files a/exe/hjha-console/hjha-console.dll and b/exe/hjha-console/hjha-console.dll differ diff --git a/exe/hjha-console/hjha-console.pdb b/exe/hjha-console/hjha-console.pdb index ce88349c..85b2e1b6 100644 Binary files a/exe/hjha-console/hjha-console.pdb and b/exe/hjha-console/hjha-console.pdb differ