目录
前言
写这篇文章的原因是因为我正在编写一个国际象棋GUI,需要用到UCI协议,但苦于找不到UCI协议的完整定义,最后在外网才找到,所以在此记录一下
1.UCI协议的特点
- 协议与操作系统无关。
- 所有的指令与输出都是通过stdin(标准输入)和stdout(标准输出)来传输的。
- 引擎应该尽可能快启动并等待来自GUI的命令并等待
isready”
或setoption
命令来设置其内部参数 - 引擎必须始终能够处理来自stdin的输入,即使是在思考的时候
- 引擎与界面的通信是以行缓冲方式进行的,也就是说,引擎收到的所有命令字符串都以
\n
结尾,GUI收到的所有输出也应该以\n
结尾 - 在没有收到
go
命令之前,引擎不应该开始计算或思考 - 在引擎被要求在一个局面上进行搜索之前,总是会有一个命令来告诉引擎当前的局面
- 默认情况下,所有的开局处理都是由GUI完成的,但有一个选项可以让引擎使用它自己的开局书(
OwnBook
选项,见下文) - 如果引擎或GUI收到一个未知的命令或标记,它应该只是忽略它并尝试解析字符串的其余部分
- 如果引擎收到一个不应该出现的命令,例如,当引擎没有在思考时出现的
stop
命令,引擎应该忽略该命令
2.走棋格式
UCI协议用的走棋格式是长代数格式
,即走动子的起始位置和到达位置,这里有几点需要注意:
- 不要标明
到达记号
、吃子记号
、将军记号
以及其他评注记号,例如第一步走e4
,则记作e2e4
,而不是e2-e4
; - 不要标明所走的子,例如走
Nf6
,则记作g8f6
,而不是Ng8f6
; - 王车易位时只标明
王的路线
,例如走O-O
,则记作e1g1
; - 兵升变时在最后注明只用
一个字母
注明升变的子
,例如走e8=Q
,则记作e7e8q
。
3.界面到引擎
3.1 uci
告诉引擎使用UCI协议,这将作为引擎启动后的第一个命令发送,以告诉引擎切换到UCI模式。
在收到UCI命令后,引擎必须用 id
命令来帮助GUI识别自己的身份。
并发送 option
命令以告诉GUI该引擎支持哪些引擎设置(如果有的话)
之后,引擎应该发送 uciok
来确认UCI模式
如果在一定时间内没有发送uciok,引擎进程将被GUI杀死
3.2 debug [ on | off ]
开启或关闭引擎的调试模式。
在调试模式下,引擎应该向GUI发送额外的信息来帮助调试,例如,用 info string
命令
这个模式应该在默认情况下被关闭,这个命令可以在任何时候被发送,包括引擎思考时
3.3 isready
这是用来使引擎与GUI同步。当GUI发送了一条或多条命令,可能需要一些时间来完成时、这个命令可以用来等待引擎再次准备好
或者用来确认引擎是否在正常运行。
例如,这条命令应该在设置tablebases
的路径之后发送,因为这可能需要一些时间。
在引擎被要求做任何搜索之前,也需要这个命令,以等待引擎完成初始化。
这条命令必须总是以 readyok
来回答,也可以在引擎正在计算的时候发送。
在这种情况下,引擎也应该立即回答 readyok
而不停止搜索。
3.4 setoption name [ value ]
这条命令用于改变引擎的内部参数或触发某个动作。
这将只在引擎空闲时发送。
选项的名称不应区分大小写,可以包含空格,值也一样。
应该避免使用 "value "和 "name "这两个子字符串,以避免含糊的解析。
例如,不要使用 “draw value” 作为选项名。
下面是一些例子:
setoption name Nullmove value true\n
setoption name Selectivity value 3\n
setoption name Selectivity value 3\n
setoption name Style value Risky\n
setoption name Clear Hash\n
setoption name NalimovPath value c:\chess\tb\4;c:\chess\tb\5\n
3.5 register
这是尝试注册一个引擎的命令,或者告诉引擎,注册将在以后进行。
将在以后进行。如果引擎在程序启动时发送了 “注册错误”,应该总是发送这个命令。
的情况下,应该总是发送这个命令。
允许使用以下标记:
- later
用户现在不想注册引擎。 - name
该引擎应该用这个名字来注册 - code
该引擎应该用代码来注册
例子:
register later
register name Stefan MK code 4359874324
3.6 position [fen | startpos ] moves …
在内部棋盘上设置fenstring
中描述的局面,并在内部棋盘上思考。
如果是初始局面,将发送 startpos
字符串。
一般来说,界面发送给引擎的fenstring
是最近一次吃子或进兵后的局面(称为不可逆局面
),该局面到当前局面的一系列着法则跟在moves后,目的是让引擎掌握重复检测的策略
如果这个fenstring
与发送给引擎的最后一个fenstring
不同,GUI应该在两者之间发送一个 ucinewgame
。
3.7 go
在用 position
命令设置的当前局面上开始计算。
在这个命令之后有许多可选参数,所有的参数都将紧随在go的后面(不应该换行)。
如果有一个参数没有被发送,其值应被解释为不会影响搜索。
- searchmoves …
使引擎只在指定的几步棋中选择一个
例如:在position startpos
和go infinite searchmoves e2e4 d2d4
之后
引擎应该只搜索初始位置中的两步棋e2e4和d2d4。 - ponder
在后台模式中开始思考,此时引擎的时钟失效。 - wtime x
白方剩余时间(所有的时间单位都是毫秒) - btime x
白方剩余时间 - winc t
白棋每步增加的时间 - binc t
黑色每步增加的时间 - depth x
只搜索x层。 - nodes x
只搜索x节点。 - mate x
在x步棋中搜索一个杀棋 - movetime x
准确搜索x毫秒 - infinite
一直搜索直到接收到stop
命令
3.8 ponderhit
在后台思考(go ponder)还没有输出结果(bestmove)时,告诉引擎后台思考命中(正在后台思考的着法正好是对手的着法),随后引擎就自动转入正常思考(时钟开始有效)。如果后台思考没有命中,就必须用stop中止思考,重新设置局面让引擎思考。
4.引擎到界面
4.1 id
这必须在收到 uci
命令后发送,以识别引擎。
- name
返回引擎的名称、
例如,id name Shredder X.Y\n
- author
返回引擎的制作者
例如:id author Stefan MK\n
4.2 uciok
必须在id和可选选项之后发送,以告诉GUI,引擎已经发送了所有信息,并且已经准备好进入uci模式。
已经发送了所有的信息,并且在UCI模式下已经准备好了。
4.3 readyok
当引擎收到 isready
命令并且已经处理了所有的输入并准备接受新的命令时,必须发送这个命令。
处理了所有的输入并准备好接受新的命令。
它通常是在一个可能需要一些时间的命令之后发送,以便能够等待引擎,
但它可以在任何时候使用,甚至在引擎正在搜索的时候,也必须总是用 readyok
来回答。
4.4 bestmove [ ponder ]
引擎已经停止了搜索,并找到了这个位置上的最佳棋步。
如果引擎停止搜索,就必须发送这条命令,当引擎正在思考时,如果有stop
命令,也必须发送。
所以每一个 go
的命令都需要返回bestmove
的信息!
在这之前,引擎应该发送一个最后的 info
命令,包含最后的搜索信息。
GUI可以获取有关于最后一次搜索的完整统计数据。
4.5 copyprotection
这对受版权保护的引擎来说是需要的。在uciok
命令之后,引擎可以告诉 GUI、
它现在将检查复制保护。这是由 "拷贝保护检查 "完成的。
如果检查正常,引擎应该发送copyprotection ok
,否则发送copyprotection error
。
如果有一个错误,引擎应该不能正常工作,但不应该单独退出。
如果引擎报告copyprotection error
,GUI不应该使用这个引擎并应该显示一个错误信息
4.6 registration
对于需要一个用户名或代码来实现所有功能的引擎来说,这是需要的。
类似于 copyprotection
命令,引擎可以在uciok
命令之后发送 registration
,如果检查正常,引擎应该发送registration ok
,否则发送registration error
。
与copyprotection
命令不同,GUI可以在引擎报告错误后使用引擎。
报告错误后,GUI可以使用该引擎,但是应该通知用户该引擎没有被正确注册
并且可能无法使用它的所有功能。
此外,GUI应该提供一个对话框来打开以实现引擎的注册。为了尝试注册一个引擎,GUI可以发送
register
命令。
如果引擎在启动时发送 registration error
,GUI应该总是用 register
命令来回答(这也可以用 register later
来完成)
并以某种方式告诉用户,引擎没有被注册。
这样,引擎知道GUI可以处理注册程序,而用户将被告知引擎没有被正确注册。
4.7 info
这是go
命令的返回信息,告诉gui引擎的思考信息。
引擎可以只发送选定的信息,并且可以用一条信息命令发送多个信息、
例如:info currmove e2e4 currmovenumber 1
或者info depth 12 nodes 123456 nps 100000
。
另外,所有属于pv的信息应该一起发送
例如:info depth 2 score cp 214 time 1242 nodes 2124 nps 34928 pv e2e4 e7e5 g1f3
。
我建议在一秒钟后才开始发送 currmove
、currmovenumber
、currline
和refutation
以避免太多的流量。
可以包含的信息有:
- depth x
引擎的搜索深度 - seldepth x
选择性的搜索深度、
如果引擎发送seldepth,在同一个字符串中还必须有一个 “深度”。 - time x
搜索的时间,以毫秒为单位,这个应该和pv一起发送。 - node x
搜索到的x个节点,引擎应该定期发送这个信息。 - pv …
找到的最佳线路 - multipv x
这是在多pv模式下的信息。
它总是跟在pv后,表示该线路是第几好的线路 - score
- cp x
返回以百分兵值为单位的分数 - mate x
表示在x步内有杀棋 - lowerbound x
该分数是一个下限。 - upperbound x
该分数是一个上限。
- cp x
- currmove …
目前正在搜索的走法。 - currmovenumber x
当前搜索的棋步的编号,对于第一步棋,x应该是1而不是0。 - hashfull x
Hash表的占用率(单位是千分之一),它也会隔一定时间显示出来。 - nps x
每秒搜索x个节点,引擎应定期发送此信息。 - tbhits x
在残局表中发现的位置数。 - cpuload x
引擎的cpu使用率。 - string …
返回一些额外信息(通常是调试信息)
这行其后的所有字符将被解释为string信息 - currline …
这是引擎正在计算的当前行。
引擎在一个以上的cpu上运行。 = 1,2,3…
如果引擎只使用一个cpu,可以省略。
如果大于1,总是一起发送k个字符串中的所有k行。
只有当选项UCI_ShowCurrLine
被设置为true
时,引擎才应该发送这个。
4.8 option
这个命令告诉GUI哪些参数可以在引擎中可以被改变。
在引擎启动时,应该在uci
命令之后输出这个
如果有任何参数可以在引擎中被改变。
GUI应该解析这个信息并为用户建立一个对话框来改变设置。
注意,并不是每个选项都需要出现在这个对话框中,因为有些选项如
Pondering
、UCI_AnalyseMode
等,最好在其他地方处理或自动设置。
如果用户想改变一些设置,GUI将发送一个 setoption
命令给引擎。
每一个可以改变的选项都会有一个option
输出。
-
name xxx
该选项的名称为xxx。
某些选项有一个固定的值,这意味着这个选项的语义是固定的。
通常这些选项不应该显示在GUI的正常引擎选项窗口中,而应该得到特殊处理。
例如,Pondering
应该在后台思考被启用或禁用时自动设置。
在GUI选项中启用或禁用时,"Pondering "应该被自动设置。同样,UCI_AnalyseMode
也应该由GUI自动设置。
也应该由GUI自动设置。所有这些选项的前缀是UCI_
,除了下面的前6个选项。
如果GUI得到一个前缀为UCI_
的未知选项,它应该只是忽略它,不在引擎的选项对话框中显示它。- Hash,类型为spin
可以改变哈希表的大小(MB)
这应该由程序启动时的第一个setoptions
命令来设置。
引擎应该首先使用一个非常小的哈希值作为默认值。 - NalimovPath,类型为string
这是硬盘上通往Nalimov压缩格式的路径。
多个目录可以用;
连接起来。 - NalimovCache, 类型为spin
这是Nalimov表的缓存的大小,单位是MB。
最后两个选项也应该出现在当引擎启动时的初始选项交换对话框中,如果引擎支持它的话 - Ponder,类型为check
这意味着引擎能够进行思索。
GUI将在思考是否可行的时候发送这个信息。
注意:如果启用了这个选项,引擎不应该自己开始思考,这个选项只是当允许思考时,使引擎改变其时间管理算法。 - OwnBook,类型为check
这意味着引擎有自己的书,可以由引擎自己访问。
如果设置了这个选项,引擎就会负责打开棋谱,而GUI将永远不会
执行从它的棋谱中移出引擎的动作。如果GUI将此设置为false、
引擎不应该访问它自己的棋谱。 - MultiPV, 类型为spin
引擎支持多重最佳线或K-best模式。默认值为1 - UCI_ShowCurrLine,类型为check,默认为false、
引擎可以显示它正在计算的当前行。见上面的 “info currline”。 - UCI_ShowRefutations,类型false,默认值为false
引擎可以在一行中显示一步棋和它的反驳。见上面的 “info refutation”。 - UCI_LimitStrength,类型为check,默认值为false
引擎能够将其强度限制在一个特定的Elo数、
这应该总是与 "UCI_Elo "一起实现。 - UCI_Elo, 类型为spin
引擎可以在这个区间内限制其Elo强度。
如果UCI_LimitStrength被设置为false,这个值应该被忽略。
如果UCI_LimitStrength被设置为true,引擎应该用这个特定的强度进行比赛。
这应该总是与 "UCI_LimitStrength "一起实施。 - UCI_AnalyseMode,类型为check
当分析或玩一个游戏时,引擎想表现得不同。
例如,当游戏时,它可以使用某种学习方法。
如果引擎正在玩游戏,这将被设置为假,否则为真。 - UCI_Opponent, 类型为string
通过这个命令,GUI可以向引擎发送名称、标题、ELO以及引擎是在和人类还是电脑比赛。
字符串的格式必须是[GM|IM|FM|WGM|WIM|none] [|none] [computer|human] 。
例如:
“setoption name UCI_Opponent value GM 2800 human Gary Kasparow”
“setoption name UCI_Opponent value none none computer Shredder”
- Hash,类型为spin
-
type
该选项的类型。
引擎可以发送5种不同类型的选项- check
一个复选框,可以是true,也可以是false。 - spin
一个旋钮,可以是一定范围内的整数。 - combo
一个选择框,可以有不同的预定义字符串作为值。 - button
一个按钮,按下后可以使引擎引擎做一个动作。 - string
一个文本字段,其值为一个字符串、
空字符串的值为""
- check
-
default x
这个参数的默认值是x -
min
该参数的最小值为x(用于spin类型) -
max
这个参数的最大值是x(用于spin类型) -
var
此参数的选项为x
例子:
这里有5个字符串,分别代表5种可能的选项类型
option name Nullmove type check default true\n
option name Selectivity type spin default 2 min 0 max 4\n
option name Style type combo default Normal var Solid var Normal var Risky\n
option name NalimovPath type string default c:\\n
option name Clear Hash type button\n
实操演示
下列展示在stockfish_15.1_win_x64_popcnt进行
uci
id name Stockfish 15.1
id author the Stockfish developers (see AUTHORS file)
option name Debug Log File type string default
option name Threads type spin default 1 min 1 max 1024
option name Hash type spin default 16 min 1 max 33554432
option name Clear Hash type button
option name Ponder type check default false
option name MultiPV type spin default 1 min 1 max 500
option name Skill Level type spin default 20 min 0 max 20
option name Move Overhead type spin default 10 min 0 max 5000
option name Slow Mover type spin default 100 min 10 max 1000
option name nodestime type spin default 0 min 0 max 10000
option name UCI_Chess960 type check default false
option name UCI_AnalyseMode type check default false
option name UCI_LimitStrength type check default false
option name UCI_Elo type spin default 1350 min 1350 max 2850
option name UCI_ShowWDL type check default false
option name SyzygyPath type string default <empty>
option name SyzygyProbeDepth type spin default 1 min 1 max 100
option name Syzygy50MoveRule type check default true
option name SyzygyProbeLimit type spin default 7 min 0 max 7
option name Use NNUE type check default true
option name EvalFile type string default nn-ad9b42354671.nnue
uciok
setoption name Threads value 2
setoption name clear hash
isready
readyok
readyok
go node 10
info string NNUE evaluation using nn-ad9b42354671.nnue enabled
info depth 1 seldepth 1 multipv 1 score cp 18 nodes 44 nps 14666 hashfull 0 tbhits 0 time 3 pv e2e4
info depth 2 seldepth 2 multipv 1 score cp 51 nodes 192 nps 64000 hashfull 0 tbhits 0 time 3 pv e2e4
info depth 3 seldepth 3 multipv 1 score cp 114 nodes 556 nps 139000 hashfull 0 tbhits 0 time 4 pv g1f3 a7a6 d2d4
// 此处省略亿点信息
info depth 27 seldepth 35 multipv 1 score cp 28 upperbound nodes 7162373 nps 1076724 hashfull 998 tbhits 0 time 6652 pv e2e4 c7c6
info depth 27 currmove e2e4 currmovenumber 1
info depth 27 seldepth 35 multipv 1 score cp 28 upperbound nodes 7390822 nps 1075341 hashfull 998 tbhits 0 time 6873 pv e2e4 c7c6
stop
bestmove e2e4 ponder c7c6
开源项目开发招人
我的国际象棋GUI开源项目需要更多人手开发,如果有希望加入开发,可以私信我的CSDN,或者联系marschina1@outlook.com,我将尽快回复
(没有报酬哈,但可以加入开发者名单)