要点

  • Misty 是一个用 Python 和 Rust 编写的开源迷雾国际象棋引擎,采用 GPL 许可:pip install misty-chess,或在 Mistboard 上用网页浏览器直接对弈。
  • 它沿用 Obscuro(Zhang 与 Sandholm,ICLR 2026)的做法:保留与所见一致的每一个棋盘,从中抽取固定数量的样本,再对样本运行反事实遗憾最小化。
  • 无论信念中有四百个局面还是四千万个,搜索开销都保持不变;增长的是样本遗漏的部分,而更快的搜索才能让样本变大。
  • 每一处偏离论文的地方都列出了原因,凡是测量过的也列出了代价;未解决的问题都是 GitHub issue。

Misty 是一个开源的迷雾国际象棋引擎,以 GPL 许可发布。pip install misty-chess,或者无需安装任何东西,直接在网页浏览器里与它对弈。

它实现了 Obscuro(Zhang 与 Sandholm,ICLR 2026)的架构,这是该游戏中第一个超越人类的智能体。论文没有附带代码,arXiv 和 OpenReview 上都没有。据我所知,另一个开源实现是 obscuro-chess,一个始于 2026 年 8 月的 JavaScript 移植版。Misty 是 Python 与 Rust 的实现,有文档化的引擎协议,还有一个可以与它对弈的公开服务器。下文列出了它偏离论文的每一处,附上原因,凡是测量过的也附上代价。

它运行在 Mistboard 上,这是我为这类游戏搭建的网站。2015 年 lichess 列出它可能加入的变体时,把黑暗国际象棋归入「大概是优先级最低的一些。很难防止其中的作弊(除非有办法让对局完全私密),而且它们完全缺乏观赏性。需要一套复杂的裁判系统。」Mistboard 就是那个裁判。服务器持有真实棋盘。每位棋手、每个引擎、每位观众只收到其座位被允许看到的内容,所以任何人的网页浏览器里都没有可读取的隐藏状态,而结束的对局可以完整回放,供任何人核查。

最能推动它的有三种帮助:会下迷雾国际象棋的人与它下一组对局,有迷雾引擎的人让自己的引擎与它对弈,以及任何愿意接手某个未解决问题的人。文末说明了具体做法。

问题所在

在迷雾国际象棋中,你只能看到自己棋子能走到的格子。对手的着法是看不见的。你观察到的是其后果:你的一枚棋子消失了,你一直盯着的某个格子变了,然后你从那里往回推理。

. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . p . . .
p . . . . . . .
. . P P . N P .
P P . N P P B P
R . B Q . R K .
白方所见
r . b q k . . r
. p . . . p p p
. . p b . n . .
. . n p p . . .
p . . . . . . .
. . P P . N P .
P P . N P P B P
R . B Q . R K .
真实局面
r . b q k . . r
. p . . . p p p
. . p b . n . .
. . n p p . . .
p . . . . . . .
. . . P . . . .
. . . . . . . .
. . . . . . . .
黑方所见

本站一局真实的五分钟对局中的第 9 回合,Misty 执黑。三块棋盘是同一个局面,都以白方视角摆放。白方看不到黑方的 14 个棋子;黑方看不到白方的 15 个。双方都从未看到中间那块棋盘。

这就去掉了每个经典引擎赖以建立的前提。Stockfish 搜索的是以一个局面为根的树。在迷雾之下并不存在单一的局面,存在的是与你观察到的一切相符的所有棋盘构成的集合,你需要一着在整个集合上都站得住的棋。

把这个集合称为 P。一局棋中有两次,它小到可以画出来。

r n b q k b n r
p p p . p p p p
. . . . . . . .
. . . p . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
1.Nf3 d5 2.Ng5 之后黑方所见
r n b q k b n r
p p p . p p p p
. . . . . . . .
. . . p . . B .
. . . . . . . .
. . . P . . . .
P P P . P P P P
R N . Q K B N R
一个象
r n b q k b n r
p p p . p p p p
. . . . . . . .
. . . p . . N .
. . . . . . . .
. . . . . . . .
P P P P P P P P
R N B Q K B . R
一个马

与之相符的两个棋盘

g5 是这一横排上黑方唯一看不到的格子。

r . b q k b . r
. p . n p p p p
. . p . . n . .
p . . p . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
黑方走棋,第 6 回合
r . b q k b . r
. p . n p p p p
. . p . . n . .
p . . p . . . .
. . . . . P . P
P . N . . . . .
R P P P P . P .
. . B Q K B N R
r . b q k b . r
. p . n p p p p
. . p . . n . .
p . . p . . . .
. . . . . . . .
. . P P . . P .
P P . B P P B P
R N . Q K . N R
r . b q k b . r
. p . n p p p p
. . p . . n . .
p . . p . . . .
. . . . . . . P
. . P . . N . .
P P Q P P P P .
R N B K . B R .
r . b q k b . r
. p . n p p p p
. . p . . n . .
p . . p . . . .
. . . . . . . .
. . . P . N P .
P P P N P P B P
R . B Q . R K .
r . b q k b . r
. p . n p p p p
. . p . . n . .
p . . p . . . .
. . . . . . . N
. P . . P . . .
P B P P . P P P
R N Q . K B . R

236,480 个中的 5 个

一个真实的中局,出自下文嵌入的对局。其中四个从集合中均匀抽取;第五个是真实棋盘。

黑方从自己视野中的一个空洞推断出某枚棋子的存在,却从未看见它。这种推理在普通国际象棋里没有对应物。推理之后仍有两个棋盘成立,黑方必须走一着同时应对两者。

到了中局,已经没有什么可画的了。引擎无法针对它所处的局面选着,因为它不知道自己处在哪个局面。它选择的是一着将在所有局面中同时走出的棋。P 会变得多大,就是全部的问题所在。

截至 2026 年 9 月,在与 Misty 进行的 216 局对局中,决策面对的一致棋盘数中位数为 74,十分之一的决策面对超过 7,000 个。与人对弈的一局中最大达到 8200 万;在 Misty 自我对弈的一局中,达到 3.46 亿个不同的棋盘。论文估计这个游戏中单个信息集可高达 109。

101001K10K100K1M10M 10203040 对局数 最差 1% 最差 10% 中位数 Misty 的回合数 相符的局面数
与人类对手的 216 盘已完成对局中信念集合的大小,按 Misty 自己的回合数排列,对数刻度。色带是中间一半的对局,虚线是最差的十分之一,点线是最差的百分之一。最差 1% 的曲线止于第 28 回合,此后剩下的对局不足 100 盘,第 99 百分位数就只是最大值。坐标轴下方的条带表示仍在进行的对局数:第 1 回合 216 盘,到第 48 回合剩 11 盘。

第一个决策面对的永远恰好是 20 个棋盘,每个合法的开局着法对应一个。到第十二个决策,中位数仍只有 84,而最糟的十分之一面对 19,427 个,最糟的百分之一峰值接近 250 万。随后,接触会让它缩减。每一次吃子、每一枚走进视野的棋子都是信息,到第四十五个决策时(在持续到那么久的对局中),中位数已降到 42。这是游戏本身的性质,而不是一种策略:Misty 没有奖励获取信息的项,也不会刻意寻求接触,而这正是它可以学会的更有意思的事情之一。

对局

四盘对局:两盘展示 Misty 如何推理它看不见的东西,一盘里迷雾让双方都陷入混乱,还有一盘负局,展示了信念规模的代价。每个棋盘上方都有「白方」「真实」「黑方」切换:选择一方,就只看到那一方能看到的内容。

Misty 自我对弈,每着三十秒。一次吃子让黑方得知白方的后只可能在一个格子上。黑方把马走到白方看不见的格子去攻击它,下一着吃掉了后。看得见整个棋盘的 Stockfish 不会走这步马;但在迷雾下,这一着赢了。这个研究收录了全部十一盘自我对弈对局。

Misty 对阵一位匿名访客,时间控制为十分钟加五秒。11…b6 之后,a6 上的一枚黑马无人保护,Misty 连续五着都没有去吃:在它认为可能的大多数局面里,这个格子有保护,通常是一枚象,而这枚象其实在第 2 着就已离开 c8,不在它的视野之内。当第二个攻击者就位时,它用象去吃,冒的是丢象而不是丢后的风险。访客同样看不见白方在 a3 上的后,用后回吃,结果丢了后。访客在第 37 着认输。

另一盘自我对弈展示了双方都看不清时迷雾会造成什么。黑方在白方看不到的地方进行了后翼王车易位,当一枚黑马落到 c5 时,白方吃掉了它:它以为后面的 d8 格上是黑方的后,认为那里是车的可能性只有大约百分之一。这次吃子打开了 d 线,直指白方自己的后。此后,两个后都在双方都看不全的棋子之间横冲直撞,子力每隔几着就出现摇摆,最后白方锁定了它需要的那一个事实,对局结束。它从未见过黑方的王,但它认为可能的每一个局面都把王放在 c8,而 27.Re8+ 找到了它。

还有一盘负局,输给一位朋友,展示了信念规模的代价。第 30 着,Misty 吃掉了一个它认为大概有保护的车,安全检查中的一个漏洞放过了这次吃子;为这个车丢掉的后,正是促成 1.6 的原因。随后,稳操胜券的白方在 Misty 看不见的地方悄悄走棋。每一着看不见的棋都让 Misty 必须保留的局面成倍增加:吃子后是 4 个,五着之后是 55,000 个,然后是 140 万、360 万和 650 万。它的着法用了 9 秒、11 秒,然后是 16 秒,而预算是五秒。下一次更新要处理 950 万个局面,超过了服务器的回复时限,服务器判 Misty 负,而它的棋钟上还剩将近四分钟。Misty 与人对弈的研究里还有七盘。

Misty 如何选着

共六步,遵循论文,采用 1.6 版本附带的设置(v1.6-net-prune 配置,位于 misty-chess 0.1.3 中)。

信念:每一个一致的棋盘

对手走出看不见的一着后,Misty 依据观察到的内容过滤 P,丢弃观察所排除的每一个棋盘。自己走完一着后,它把每个棋盘向前推进。P 是精确维护的,每一个一致的局面都由 Rust 枚举出来,每一着都重新构建:没有粒子滤波,没有近似。生产环境把它的上限设为 1600 万个局面。

超过上限时,Misty 保留一个均匀随机样本继续下棋;记录中最糟的一局因此峰值达到 7.7 GB。在唯一越过上限的那一局(6 月)中,对手在视野之外将一个兵升变,信念增长到 8200 万个棋盘,真实局面从样本中掉了出去。Misty 接下来的两个决策,面对的集合中并不包含它实际所在的棋盘。随后,新的后吃掉了它的王。每一着只由上一着构建,所以没有任何东西能把真相找回来;用新的抽样种子重放观察历史就可以做到(#10)。如果 P 变为空集,引擎会抛出异常而不是修补它,因为空集意味着观察模型有错。

Rust 枚举器比 Python 版本快大约 500 倍。Python 版本保留下来作为参照:测试套件重放真实对局,要求两者在每一着都一致。这项检查发现的 bug 比它付出的代价多,也是整个设计中最值得保留的部分。

抽样:从 P 中取固定数量的世界

Misty 从 P 中随机抽取固定数量的根世界:1.6 中是 32 个,这是配置中的一项设置,而论文用的是几百个。固定这个数量,正是搜索开销不随信念增长的原因:无论 P 中有四百个局面还是四千万个,搜索看到的数量都一样。为什么不调高它,是一个关于时间的问题,答案见一着棋的开销。

每个一致的棋盘获得相同的权重,尽管它们的可能性并不相同。一个对手花了三步来回挪动车的棋盘符合证据,但实际上几乎不可能出现。Misty 没有对手模型来区分它们。Obscuro 也没有。obscuro-chess 有:一个在 246 盘 Chess.com 对局上拟合的着法先验。

搜索:一棵以 Misty 所见为键的树

抽样出的世界共同生长出一棵博弈树。树中的一个节点是一段观察历史:轮到走棋的一方到目前为止看到的一切。在 Misty 看来完全相同的世界落在同一个节点上,共享同一个策略。这种分组就是信息集的含义,也是搜索只返回一个答案的原因。

这排除了最显而易见的做法,即把每个世界交给 Stockfish 再统计票数。投票会让你在无法区分的局面中走出不同的着法,而在棋盘前你做不到这一点。把 Stockfish 在各个世界的评估值取平均也行不通,原因更隐蔽:每个评估值都假设走完这一着后,你会知道自己处在哪个世界。

取两个可能性相同的世界和两着棋。走等待之后,下一着是在两个格子之间猜:猜对就赢,猜错就输。稳妥在两个世界中都有一点小优势。

                 world 1   world 2   average   really
wait, then guess   +1        +1        +1        0
safe               +0.3      +0.3      +0.3     +0.3

每次只拿到一个世界时,Stockfish 总能猜对,因为在它的世界里没有什么可猜的,于是等待的平均结果是必胜。在棋盘前,Misty 无法区分这两个世界,只有一半的时候猜对,等待一文不值。搜索通过把看起来相同的世界放在同一个节点上来避免这一点,这迫使两者作出同样的猜测。

对手也有发言权。他们决定你能看到什么,所以如果你对某个隐藏威胁总是以同样的方式应对,他们就会学会,并把局势引向你没有覆盖的分支。Misty 寻找的是面对一个知道它如何决策的对手时让步最少的策略。有时这个策略就是在两着之间抛硬币。

找到它的工具是反事实遗憾最小化,也就是攻克了扑克的那一类算法。

每个节点持有一个混合策略:每着一个概率,初始时均等。对树的一次遍历自底向上做四件事:

leaf       v = tanh(centipawns / 500)
move       v(a) = average of a over the worlds
node       v(I) = Σ x(a) · v(a)
regret     R(a) ← max(0, R(a) + v(a) − v(I))
next mix   x(a) ∝ max(0, R(a) + Δ(a))

其中 x 是节点当前的混合策略,Δ(a) 是 R(a) 刚刚得到的变化量。第一行把 Stockfish 的评估值放到 −1 到 +1 的刻度上:多一个兵约为 +0.2,多一个车约为 +0.75,吃掉王恰好是 +1。第二行和第三行是平均值。在轮到对手走棋的节点上,其值按对手当前的混合策略加权,所以一着棋的值,就是它在 Misty 无法区分的所有世界中、针对对手此刻的下法所能获得的收益。

遗憾是一个累计总和,记录每一着比混合策略好了多少。假设某个节点以各一半的概率走两着,这一遍中它们的得分分别为 +0.12 和 +0.08。节点的值为 +0.10,所以第一着获得 0.02 的遗憾,第二着降到零,因为遗憾永远不会为负。下一遍时,混合策略就偏向第一着。与此同时,每个对手节点都针对 Misty 的混合策略做了同样的事,这会改变各个值,进而再次改变混合策略。当任何节点上都没有一着能胜过其自身的混合策略时,遍历就不再改变任何东西。这就是均衡,而它需要成千上万遍而不是一遍,因为双方都在相互调整。

最小的版本可以放进一张表。你可以守护两个格子中的一个,而对手攻击一个你看不见的格子。a 遭到无人守护的攻击会让你损失整整一分,b 则损失半分。运行同样的更新,双方同时进行:

遍数 你守护 a 对方攻击 a
1 100% 0%
2 11% 87%
3 83% 53%
10 72% 28%
20 67% 33%

起初双方都对彼此反应过度,然后趋于稳定:三次中有两次守护 a,此时任何一方改变做法都得不到更好的结果。这个稳定下来的混合策略,就是搜索要寻找的东西。

最后一行是相对普通遗憾匹配的唯一改进。加上最近一次的变化量,相当于预测下一遍会和这一遍相似。正因如此,Misty 最后可以按当前的混合策略下棋,而不是按它经历过的所有混合策略的平均值;这一类算法叫作预测式 CFR+。

r . b . k b . r
p p p q p p p p
. . n . . n . .
. . . p . . . .
. . . . . . . .
N . . . P N P .
P P P P . P R P
R . B . K B . .
r . b . k b . r
p p p q p p p p
. . n . . n . .
. . . p . . . .
P . . . . . . .
N . . . P N P .
. P P P . P . P
R . B . K B R .
r . b . k b . r
p p p q p p p p
. . n . . n . .
. . . p . . . .
. . . . . . . P
. . . . P . P .
P P P P . P N .
R N B . K B . R
r . b . k b . r
p p p q p p p p
. . n . . n . .
. . . p . . . .
. . . . . . . .
. . . . P P P .
P P P P N . K P
R N B . . B . R

从 12,567 个中抽取的 32 个世界里的四个。着色的是这四个世界有分歧的 13 个格子,而黑方一个也看不到,所以在搜索看来这四个是同一个局面。

e50.389Qf50.388a50.155h50.06701.0

黑方 30 个合法着法上的一个策略。另有 5 个着法合计不到 0.001。

由于每个抽样世界呈现给黑方的观察历史都相同,它们共享搜索树中的同一个节点,这步五秒棋的 20,768 次迭代都在那里一起累积遗憾。输出是单一的分布。之后还必须把它落成一步棋,在这里就是在 0.0017 的差距上把 e5 和 Qf5 分开。

这是一个五秒时限下的真实决策,也展示了实践中出现的抛硬币:两着棋相差不到 0.002。每次迭代是对所有节点的一次遍历,再加一个新叶子。到 2,000 个叶子时,树停止生长,遍历在固定的树上继续进行,直到时间用完,所以一着棋的大部分迭代是在细化混合策略,而不是扩展树。时间是唯一的停止规则;没有任何东西检查混合策略是否已经稳定(#8)。

范围:求解到多远

在迷雾下,固定深度是个错误的停止位置。重要的是一个局面离某个可能被人与之混淆的局面有多远。只要任一方无法区分两个节点,Misty 就把它们合并,并且只扩展在几步这种距离之内的叶子,而这正是它开始推理对手对它有哪些不知道的地方。

评估值:叶子上的 Stockfish

新叶子由深度为一的 Stockfish 18 打分。它以单线程、16 MB 哈希表运行,从源码在一个固定的提交上构建,确保每次部署运行的都是同一个二进制文件。在固定版本之前,生产环境运行的是 Linux 发行版自带的版本,即 14;在唯一一组比较两者的实验中,它们的差距在噪声范围内。没有再进一步扫描其他版本,因为叶子评估只占一着棋耗时的 11%。Stockfish 从不见到迷雾。它只回答「这个具体的棋盘有多好」,这是它回答得最好的问题,而迷雾推理留在上面一层。这带来了一个上层无法弥补的代价:兵的对峙对经典引擎来说是中性的,在迷雾下却是决定性的,因为谁吃子谁就获得视野。论文估计评估器的分量约为 262 Elo。

落子:从一个分布中选出一着

搜索结束时,每一着都有一个概率,Misty 走概率最高的那一着。Obscuro 可以安全地在多着之间混合,因为它会用上一着沿用下来的策略来检查候选着法。Misty 在两着之间会丢掉它的树,所以没有什么可以用来检查混合,而强制混合的结果是 0 胜、7 负、1 和。

护栏最后运行,否决那些在足够多的信念中会丢掉大子或让王走进被吃位置的着法。它们不在论文中,也不是罕见的兜底:在上面的十一盘对局中,它们替换了 17% 着法中搜索的选择。它们能拦住那些让引擎在人类眼中显得愚蠢的错误,也会造成一些自己的错误。在上面那盘自我对弈中,双方最糟糕的着法里有三着是护栏的选择,而不是搜索的:它们只往前看一着,而兵的双击需要两着。一个能自己看到这些危险、从而可以去掉护栏的搜索,是其他大多数问题之下的那个未解决问题。

设置

设置项 发布值 调高的效果
信念上限 16,000,000 个局面 精确性保持得更久,代价是数 GB 内存
抽样的根世界 32 看到更多信念,每个世界的迭代更少
扩展预算 每着 2,000 个叶子 树更宽,遍历更慢
范围阶数 2 子博弈更大,每着重新求解的部分更多
叶子评估深度 1 叶子得分更好,数量大幅减少
每着时间预算 5 秒 以上所有项按比例提升

根世界、扩展和范围设置在配置 v1.6-net-prune 中;信念上限和每着时间预算由调用方提供;叶子深度在评估器中固定。阶数为 2 时,三步混淆距离内的叶子可以扩展,而一到两步之间的区域会在搜索中重新求解。

一着棋的开销

生产环境中的每一着都会记录时间花在了哪里。913 着的平均值:

步骤 平均 占比
均衡遍历 3.91 秒 69%
新叶子上的 Stockfish 0.61 秒 11%
扩展的其余部分 0.18 秒 3%
叶子选择 0.16 秒 3%
范围 0.06 秒 1%
搜索之外:信念更新、护栏、落子、传输 0.68 秒 12%
合计 5.68 秒  

均衡遍历是每次迭代对树中每个节点的更新,所以它占了大头。信念更新,这个人人以为开销很大的步骤,平均只要 6 毫秒。护栏在搜索计时停止后才运行,所以五秒的一着要花 5.7 秒;在本地剖析的一个决策中,护栏用了 1.2 秒。

一着棋受实际耗时约束:time_budget_seconds,生产环境中为 5,棋钟可以把它调低。配置中还有一个迭代上限,设为一千万,保证总是时间先到。如果既不传时间预算也没有棋钟,迭代上限就成为停止规则。一次 5,000 次迭代的运行在三个独立进程中选出了同一着棋,构建了同一棵树,给出了相同的前四个概率。任何想要复现的场景都应该用这种模式,因为限时的一着取决于机器当时有多快。

开销也是那个显而易见的问题的答案:论文用几百个世界,为什么只抽样 32 个?每一遍都要走遍每一个世界,所以一遍的开销与世界数量成正比。同一局面,同样的时间:

根世界数 5 秒内的迭代次数 树节点数
32,发布值 45,068 6,322
128 10,645 25,291
200 5,958 43,070
256,论文范围的上限 4,958 52,557

世界数增加到八倍,换来的是遍历次数减少到九分之一。2,000 个叶子的预算也由各个世界分摊,所以在 256 个世界时,每个世界大约只得到八个叶子而不是六十个,而且一着棋 40% 的时间里树还在生长。在 32 个世界时,树很早就长完了,大约 43,000 次遍历在它上面细化混合策略。更多的世界能看到更多的信念,但每个都解得更差。在固定五秒的对抗中,64、128 和 200 个世界的配置在除一项之外的所有对比中都输给了 32。

所以要调高它,首先需要吞吐量,而吞吐量就在均衡遍历上。把它限制在扩展已经遵守的范围内(#6),或者把它拆分到多个核心上,才能带来成倍的提升。照搬论文中一个求解线程、两个扩展线程的划分则不行:它并行化的是扩展,而扩展只占时间的 14%。计时数据取决于机器,所以这里的笔记本数据只能相互比较,不能与生产环境比较。

与论文对照

Misty 以 Obscuro 为指导,而不是对它的忠实复现。逐行与论文对照:

论文中 这里 原因
搜索树和均衡在着法之间沿用 每着丢弃并重新抽样 1.1 中构建,1.2 中移除;见下文
按信息集分配的到达礼物 单一标量边际,设为零 未构建
为安全装置准备的蓝图策略 P 较小时覆盖率约 38%,规模大时约为 0 第一行的后果
Resolve 与 Maxmargin 两种模式,相互切换 仅 Resolve 切换功能藏在一个环境变量之后,从未发布
由几百个世界组成的根集合 32 吞吐量;见一着棋的开销
带部分剪枝的 CFR,一次迭代的耗时通常随树的规模亚线性增长 每次迭代都遍历整棵树 未构建;树停在 2,000 个叶子正是因为它(#6)
一个求解线程和两个扩展线程共享一棵树 单线程 未构建,而且它并行化的是本来就分不到多少时间的那部分

第一行导致了第二行和第三行。蓝图就是上一着的搜索,所以在根重新抽样的情况下,P 较小时它覆盖约 38% 的世界,规模大时一个也覆盖不到。没有它,Misty 的安全装置会过度防守,因此只在开局中运行。

沿用树在 1.1 中构建,在 1.2 中移除:在开局中,它在真实棋盘上造成约 125 厘兵的损失,迭代次数少了 21%。中局才是 P 很大、蓝图会起作用的地方,也是它应该有回报的地方。

下一步

这些工作以 issue 形式跟踪,都在棋力(strength)标签下,每个都附有证据、拟议的修复,以及能证明修复有效的测量方法。按各自预期的收益排序:

  1. 吞吐量(#6)。均衡遍历在每次迭代中都会走遍整棵树,尽管范围已经限制了哪些叶子可以生长。以同样的方式限制遍历,带来的应该是倍数级而不是百分比级的提升,而世界数量正等着它:在当前速度下由 32 个世界胜出的那组对抗,会在新的速度下重新进行。
  2. 中局中的沿用树(#11)。在信念较小的开局中,在着法之间沿用搜索造成了约 125 厘兵的损失。论文说中局才是它有回报的地方,而在着法之间混合以及一个有效的安全装置都依赖于它。
  3. 不需要护栏的搜索。护栏替换了 17% 着法中搜索的选择,也造成了一些最糟糕的着法。像兵的双击这样两着之内的危险,必须由搜索自己看到;检验方法是关闭护栏进行一次对抗赛。
  4. 已知解法形态的修复:利用时间储备(#7),在混合策略稳定时而不是时间用完时停止(#8),把对光杆王的必胜残局赢下来(#9),以及在超过信念上限后找回真实棋盘(#10)。

本文介绍的是 2026 年 9 月的 1.6 版本。issue 反映的是当前状态。

来下棋、来测试、在它之上构建

来下棋。Misty 在 Mistboard 上,无需账号,无需安装。那里的机器人运行的正是仓库发布的同一引擎和配置。与人对弈的对局是 Misty 最稀缺的数据,它们能展示自我对弈展示不了的东西。

联系我。如果你下迷雾国际象棋并想和它下一组,研究不完全信息博弈,想在研究或项目中使用 Misty,或者在本文中发现了错误,请发邮件到 contact@brianhliou.com。

在它之上构建。pip install misty-chess 即可获得引擎;README 介绍了 Rust 扩展以及纯 Python 回退方案的代价。引擎通过 stdio 使用 JSON 协议通信,仓库中有文档。服务器只发送经过遮蔽的观察,所以运行中的引擎无从获知真相。

带上你的引擎。Misty 几乎没有可以衡量自己的对手。任何支持该协议的迷雾国际象棋引擎都可以在同一个服务器上与它对弈,无论结果如何都会公布。