diff --git a/PdkFriendServer/Logic/IsmctsBot.cs b/PdkFriendServer/Logic/IsmctsBot.cs index a62e209c..c17d2d3e 100644 --- a/PdkFriendServer/Logic/IsmctsBot.cs +++ b/PdkFriendServer/Logic/IsmctsBot.cs @@ -164,16 +164,19 @@ namespace PdkFriendServer.Logic if (SimulateToEnd(hand, view, play)) wins++; - // 有前途的候选多模拟 double fastRate = (double)wins / fastSims; + + // 胜率太低 → 剪枝,不参与后续评估 + if (fastRate < 0.15 && allCandidates.Count > 3) + continue; + + // 有前途的候选多模拟 int extraSims = fastRate > 0.3 ? simsPerCandidate - fastSims : 0; for (int s = 0; s < extraSims; s++) if (SimulateToEnd(hand, view, play)) wins++; double totalRate = (double)wins / (fastSims + extraSims); - - // 牌效率:出牌后剩余手牌的最少步数 int afterMin = HandOptimizer.MinPlays( hand.Where(c => play.Ids == null || !play.Ids.Contains(c.ID)).ToArray()); @@ -181,6 +184,22 @@ namespace PdkFriendServer.Logic scoredCandidates.Add((play, totalRate, afterMin, allCandidates[ci].isMulti)); } + // 如果所有候选都被剪枝,回退到不做剪枝,全部重新评估 + if (scoredCandidates.Count == 0) + { + for (int ci = 0; ci < allCandidates.Count; ci++) + { + int wins = 0; + var play = allCandidates[ci].play; + for (int s = 0; s < fastSims; s++) + if (SimulateToEnd(hand, view, play)) wins++; + double rate = (double)wins / fastSims; + int am = HandOptimizer.MinPlays( + hand.Where(c => play.Ids == null || !play.Ids.Contains(c.ID)).ToArray()); + scoredCandidates.Add((play, rate, am, allCandidates[ci].isMulti)); + } + } + // 4. 多牌加权 for (int i = 0; i < scoredCandidates.Count; i++) { @@ -460,7 +479,11 @@ namespace PdkFriendServer.Logic } current = current % 3 + 1; } - return hands[myPos - 1].Count <= hands[nextPos - 1].Count && hands[myPos - 1].Count <= hands[oppPos - 1].Count; + // 截断:用 MinPlays 评估而非比较张数 + int myMin = HandOptimizer.MinPlays(hands[myPos - 1].ToArray()); + int n1Min = HandOptimizer.MinPlays(hands[nextPos - 1].ToArray()); + int n2Min = HandOptimizer.MinPlays(hands[oppPos - 1].ToArray()); + return myMin <= n1Min && myMin <= n2Min; } // ---- 多牌先手枚举 ---- @@ -479,20 +502,48 @@ namespace PdkFriendServer.Logic var triples = GetMultiGroups(hand, 3); foreach (var t in triples) { - var rem = hand.Where(c => c.GameNum != t[0].GameNum).OrderBy(c => c.GameNum).ToList(); + var rem = hand.Where(c => c.GameState == 1 && c.GameNum != t[0].GameNum).ToList(); if (rem.Count >= 2) - AddCandidate(t.Concat(rem.Take(2)).ToList(), pos, candidates); // 三带二 + { + // 三带二:优先带对子(对子本身是一手牌),找不到对子才带两张最小散牌 + var pair = rem.GroupBy(c => c.GameNum) + .Where(g => g.Count() >= 2) + .OrderBy(g => g.Key) + .FirstOrDefault(); + if (pair != null) + AddCandidate(t.Concat(pair.Take(2)).ToList(), pos, candidates); + else + AddCandidate(t.Concat(rem.OrderBy(c => c.GameNum).Take(2)).ToList(), pos, candidates); + } else AddCandidate(t, pos, candidates); } - // 四带二/三 + // 四带二/三:优先带对子 var quads = GetMultiGroups(hand, 4); foreach (var q in quads) { - var rem = hand.Where(c => c.GameNum != q[0].GameNum).OrderBy(c => c.GameNum).ToList(); - if (rem.Count >= 3) AddCandidate(q.Concat(rem.Take(3)).ToList(), pos, candidates); - else if (rem.Count >= 2) AddCandidate(q.Concat(rem.Take(2)).ToList(), pos, candidates); + var rem = hand.Where(c => c.GameState == 1 && c.GameNum != q[0].GameNum).ToList(); + var pair = rem.GroupBy(c => c.GameNum) + .Where(g => g.Count() >= 2) + .OrderBy(g => g.Key) + .FirstOrDefault(); + if (rem.Count >= 3) + { + if (pair != null) + AddCandidate(q.Concat(pair.Take(2)).Concat(rem + .Where(c => c.GameNum != pair.Key).OrderBy(c => c.GameNum).Take(1)) + .ToList(), pos, candidates); + else + AddCandidate(q.Concat(rem.OrderBy(c => c.GameNum).Take(3)).ToList(), pos, candidates); + } + else if (rem.Count >= 2) + { + if (pair != null) + AddCandidate(q.Concat(pair.Take(2)).ToList(), pos, candidates); + else + AddCandidate(q.Concat(rem.OrderBy(c => c.GameNum).Take(2)).ToList(), pos, candidates); + } } // 连对(复用 pairs,不重复 GetMultiGroups) diff --git a/exe/PdkFriendServer/PdkFriendServer.dll b/exe/PdkFriendServer/PdkFriendServer.dll index 85625179..91062576 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 5d383c66..e3c1015a 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 85625179..91062576 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 5d383c66..e3c1015a 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 69d9a937..3d2f4153 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 0f02ea0a..c348b073 100644 Binary files a/exe/hjha-console/hjha-console.pdb and b/exe/hjha-console/hjha-console.pdb differ