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 (仅模拟单张)
This commit is contained in:
2026-07-12 23:28:40 +08:00
parent 2af570c0b3
commit 30a4d06b33
7 changed files with 31 additions and 8 deletions

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using GameFix.PaoDeKuaiF; using GameFix.PaoDeKuaiF;
using GameFix.Poker;
using GameMessage; using GameMessage;
using GameMessage.PaoDeKuaiF; using GameMessage.PaoDeKuaiF;
@ -273,19 +274,41 @@ namespace PdkFriendServer.Logic
foreach (var t in tips) foreach (var t in tips)
candidates.Add((MakePlay(t, view.MyPos), t.Count > 1)); candidates.Add((MakePlay(t, view.MyPos), t.Count > 1));
if (isFirstPlay) if (isFirstPlay)
{ AddMultiCardLeads(hand, view.MyPos, candidates);
var pairs = hand.GroupBy(c => c.GameNum).Where(g => g.Count() >= 2);
foreach (var g in pairs)
{
var p = g.Take(2).ToList();
candidates.Add((new PlayOutCardPdkF { Pos = (byte)view.MyPos, GameNum = p[0].GameNum, Ids = p.Select(c => c.ID).ToArray(), Type = CardType1.DuiZi }, true));
}
}
if (!isFirstPlay) if (!isFirstPlay)
candidates.Add((Pass(view), false)); candidates.Add((Pass(view), false));
return candidates; return candidates;
} }
// 复用 IsmctsBot 的多牌枚举(对子/三张/顺子/飞机/炸弹/连对)
private static void AddMultiCardLeads(TCardInfoPdkF[] hand, int pos,
List<(PlayOutCardPdkF, bool)> candidates)
{
var make = (List<TCardInfoPdkF> cards) => candidates.Add((
new PlayOutCardPdkF { Pos = (byte)pos, GameNum = cards[0].GameNum, Ids = cards.Select(c => c.ID).ToArray(), Type = InferType(cards) }, true));
if (PokerLogic.GetPlayZhaDans(hand, out var bombs) && bombs != null)
foreach (var b in bombs) make(b);
foreach (var g in hand.GroupBy(c => c.GameNum).Where(g => g.Count() >= 2))
make(g.Take(2).ToList());
foreach (var g in hand.GroupBy(c => c.GameNum).Where(g => g.Count() >= 3))
make(g.Take(3).ToList());
var straights = PokerLogic.GetShunZi(hand);
if (straights != null) foreach (var s in straights) make(s);
}
private static CardType1 InferType(List<TCardInfoPdkF> cards)
{
int n = cards.Count;
if (n == 1) return CardType1.DanZhang;
if (n == 2) return CardType1.DuiZi;
var cnts = cards.GroupBy(c => c.GameNum).Select(g => g.Count()).OrderByDescending(x => x).ToList();
if (cnts[0] == 4) { if (n == 4) return CardType1.ZhaDan; if (n == 6) return CardType1.SiDai2; if (n == 7) return CardType1.SiDai3; }
if (cnts[0] >= 3) return CardType1.SanZhang;
if (cnts[0] == 2 && n % 2 == 0) return CardType1.LianDui;
return CardType1.ShunZi;
}
private static PlayOutCardPdkF MakePlay(List<TCardInfoPdkF> cards, int pos) private static PlayOutCardPdkF MakePlay(List<TCardInfoPdkF> cards, int pos)
=> new PlayOutCardPdkF { Pos = (byte)pos, GameNum = cards[0].GameNum, Ids = cards.Select(x => x.ID).ToArray(), Type = CardType1.DanZhang }; => new PlayOutCardPdkF { Pos = (byte)pos, GameNum = cards[0].GameNum, Ids = cards.Select(x => x.ID).ToArray(), Type = CardType1.DanZhang };

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.