DanKS共享掼蛋规则引擎深度解析:108张牌如何驱动整个AI体系
DanKS共享掼蛋规则引擎深度解析:108张牌如何驱动整个AI体系
DanKS 是由金山 AI 产品中心发起的 SOTA 级掼蛋智能体项目,其核心是一个可独立运行的共享掼蛋规则引擎。这个基于 108 张牌(两副扑克 + 大小王)的 Python 引擎 guandan/engine/,统一驱动 V1/V2/V3 三代 AI 的自博弈训练与推理——本文将带你看懂它是如何把一桌掼蛋变成 AI 可学习的结构化动作空间的。
为什么要先读懂规则引擎?
很多人以为"做牌类游戏 AI"就是写一个神经网络,但 DanKS 的架构表明:规则引擎才是整个体系的基座。
三代版本(V1 结构化召回、V2 学习型选择、V3 PPO 策略)共享同一个引擎接口:引擎负责发牌、出牌、进贡还贡、判定合法动作,AI 只负责"在合法动作里选最优"。这意味着:
- 训练时:引擎作为自博弈环境,产出海量合法对局轨迹;
- 推理时:引擎生成 legal actions,策略网络只在这组有界候选上打分;
- 升级时:V1 → V3 的算法演进完全不动规则层,各代模型可放心替换。
引擎模块拆解:5 个文件各司其职
规则引擎本体在 guandan/engine/ 下,结构非常清晰:
| 模块文件 | 职责 |
|---|---|
| table.py | 牌桌运行时 Table(对外别名 Environment):发牌、轮转阶段、结算晋级 |
| python_rules.py | 纯 Python 合法动作生成:首出与跟牌枚举全部牌型 |
| moves.py | Moves 封装合法动作列表,供 AI 按索引取动作 |
| types.py | 核心数据结构:Card、Move、Player、Trick、Finish 等 |
| environment.py | 一行转发 Table as Environment,统一对外 API |
入口导出只有三个名字——guandan/engine/init.py 中的 Environment、Moves、Move,学习成本极低。
108 张牌是如何被编码的?
在 types.py 中,每张牌被编码为一个 16 进制整数,例如 SK 对应 0x010d、大王 HR 对应 0x0211。这样设计的收益:
- 比较快:比牌大小直接用位运算
digital & 0x00FF,无需查表遍历; - 省内存:27 张手牌就是 27 个整数,自博弈百万局训练时的内存开销非常低;
- 级牌即动态:
Trick类维护rank_order与number_order,级牌(当前打几)会在每局开始时通过update_order把"几"提升为 15 位强度——这正是掼蛋"打 A 升级、打级牌变王牌"规则的落点。
另外两张王牌:红桃级牌是逢人配(万能牌),大小王组成"天王炸",都在这套编码里有明确位置。
合法动作生成:AI 的"动作菜单"
掼蛋的牌型组合极其复杂:单张、对子、三张、炸弹、三带二、连对、三连对、顺子、钢板、同花顺……python_rules.py 的 first_actions 会把手牌拆分成所有可能的首出牌型,second_actions 则根据上家的 greater_action 只枚举能压过的动作(或 PASS)。
关键在去重与规范化:每个动作都经 _canonicalize_action 归一、用 _action_key 去重,最终输出统一为 [pattern, rank, cards] 三元组。AI 拿到的 Moves 对象只是一个索引列表,action_list[i] 就是第 i 个合法出法——神经网络输出的 logit 维度和合法动作数天然对齐,不存在非法动作问题。
阶段状态机:不止是出牌
掼蛋不是"出完就结束"。Table 类用一个 loop 指针把整局切成若干阶段处理器:
- PLAY 出牌阶段(table.py 中
play()):逐家响应 PASS/压牌,记录"最大动作"; - TRIBUTE 进贡阶段(
tribute()):上局末位向冠军方进贡,含双下双贡、抗贡(持双大王)判定; - BACK 还贡阶段(
back()):贡牌方还小牌; - 结算晋级:
Finish.settlement()按首末名顺序计算升级数(一升/二升/三升),打 A 过 A 判定one_times_over或stuck_at_ace。
这套状态机意味着 AI 面对的不只是出牌决策,还有进贡选牌、还贡选牌——全部通过同一套 actIndex 消息协议与引擎交互。
三分钟跑起来:引擎独立可用
引擎可完全脱离 AI 版本单独安装使用,最短路径:
git clone https://gitcode.com/gh_mirrors/da/DanKS
cd DanKS
python -m pip install -e ".[dev]"
python examples/engine_quickstart.py
examples/engine_quickstart.py 会开一桌四人对局并自检"4 人各 27 张牌",输出 DanKS engine ready: 4 players, 27 cards each。
核心 API 只有几行:
from guandan import Environment
game = Environment(first_player=0)
for seat in range(4):
game.add_player(f"player-{seat}", seat)
messages = game.start() # 洗牌、发牌,进入出牌阶段
之后引擎通过 messages 消息队列驱动对局:每条 act 消息包含 actionList 与 indexRange,AI 只需回传 actIndex 即可完成一次出牌。引擎测试 tests/test_engine.py 对首出/跟牌枚举和开局牌数都做了断言保护。
引擎如何驱动三代 AI 体系?
结合 README.md 的总体架构,引擎在 DanKS 流水线中的位置是:
- 编码信息状态:引擎把可见手牌、公开出牌历史、
legal_actions、座位上下文打包成策略输入; - 结构化召回:versions/v3/DanKS/retrieval/ 在合法动作全集上做有预算的拆牌搜索,产出 Top-K 代表候选;
- Actor-Critic 评分:共享编码器融合状态与候选结构特征,Actor 排序、Critic 估值;
- PPO 自博弈学习:versions/v3/DanKS/training/ 基于引擎产出的轨迹做 GAE 优势估计与裁剪 PPO 更新;
- V3Pro 推理精化:versions/v3pro/DanKSPro/ 在冻结 V3 模型之上追加安全门与残局精确搜索,其
refine_endgame同样基于引擎状态做隐藏牌枚举与 minimax 校验。
可以说:108 张牌的规则引擎定住了游戏边界,三代 AI 才可能在这个边界内各自演进——这正是 DanKS "一个仓库、一个引擎、三代智能体"设计哲学最耐人寻味的地方。
小结
- 共享引擎 guandan/engine/ 是 V1/V2/V3/V3Pro 共同的训练环境与推理裁判;
- 16 进制牌编码 + 三元组动作格式,让高速比较与神经网络动作空间无缝对齐;
- 完整的 PLAY/TRIBUTE/BACK 阶段状态机,覆盖掼蛋全部规则细节;
- 引擎可独立安装运行,
python examples/engine_quickstart.py三分钟验证全部链路。
想继续深入,建议按顺序阅读:tests/test_engine.py(最小用例)→ moves.py(动作接口)→ python_rules.py(牌型枚举)→ table.py(对局状态机),即可完整掌握这套驱动 AI 体系的掼蛋规则引擎。

