ホーム>USIプロトコルとは


USI(Universal Shogi Interface)プロトコルとは、将棋GUIソフトと思考エンジンが通信をするために、Tord Romstad氏によって考案された通信プロトコルです。USIの原案は、以下で読むことができます。

The Universal Shogi Interface, draft 1

このページの文章は、原案の直訳ではなく、説明の仕方を適度に変更しています。また、前置きの部分や、将棋所で未対応のコマンドについて説明を省略しています。一方、コマンドのやり取りの方法など、全体の流れについて原文では具体例が少なくてわかりにくいと思うので、その部分については説明を増やしています。わからないところがあったら、実際に将棋所でサンプルエンジンのLesserkaiを動かして、デバッグウィンドウのログを見ると参考になると思います。

将棋所の作成にあたり、原案のままでは不足している部分があったので、その点については新しいコマンドを追加しました。そのため、このページで解説している内容を、USIの正式な定義ということにします。(何をもってUSIの正式な定義とするかはっきりしていないのですが、ここ以外でUSIについて議論している人もいないと思うので、このページの内容が正式版であるとして構わないと思います。原案を考案したTord氏も、その後、コンピュータ将棋に関しては何もやっていないようですし。)既に実装済みのコマンド部分を変更することはありませんので、エンジン作者は安心してUSIに対応して下さい。


USIプロトコル全般における注意


SFENによる盤面と指し手の表記について

USIで使用される、SFEN(Shogi Forsyth-Edwards Notation)表記法による局面と指し手の表記を解説します。この表記方法は、後述するpositionコマンドやbestmoveコマンド、さらにinfoコマンドなどで使用されます。

駒の種類は、それぞれ1文字のアルファベットで表され、先手の駒は大文字、後手の駒は小文字になります。

先手の玉:K、後手の玉:k (Kingの頭文字)
先手の飛車:R、後手の飛車:r (Rookの頭文字)
先手の角:B、後手の角:b (Bishopの頭文字)
先手の金:G、後手の金:g (Goldの頭文字)
先手の銀:S、後手の銀:s (Silverの頭文字)
先手の桂馬:N、後手の桂馬:n (kNightより)
先手の香車:L、後手の香車:l (Lanceの頭文字)
先手の歩:P、後手の歩:p (Pawnの頭文字)

駒が成った状態を表記するには、駒の文字の前に+をつけます。先手のと金は+Pとなります。

盤面を表記するとき、1段目の左側(9筋側)から駒の種類を書いていきます。空白の升は、空白が続く個数の数字を書きます。
平手初期局面の場合、1段目は、左から後手の駒が香桂銀金玉金銀桂香と並んでいるので、lnsgkgsnlとなります。2段目は、空白が1升、後手の飛車、空白が5升、後手の角、空白が1升というように並んでいるので、1r5b1となります。
各段がそのように表記され、1段目から9段目まで、それぞれの段の表記を/(半角スラッシュ)でつなげて書くと、盤面の表記になります。平手初期局面であれば

lnsgkgsnl/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL

ということになります。
しかし局面表記にはこれだけでは不十分で、次の手番と、持ち駒についても表記する必要があります。
次の手番については、先手番ならb、後手番ならwと表記します。(Black、Whiteの頭文字)

持ち駒については、先手後手のそれぞれの持ち駒の種類と、その枚数を表記します。枚数は、2枚以上であれば、駒の種類の前にその数字を表記します。先手側が銀1枚歩2枚、後手側が角1枚歩3枚であれば、S2Pb3pと表記されます。どちらも持ち駒がないときは-(半角ハイフン)を表記します。

さらにSFENの原案によると、次の手が何手目かという数字も表記する必要があります。ただし、任意局面から開始する場合など、次の手が何手目かという情報に意味がないので、これが必要なものかどうかよくわかりません。将棋所の場合、この数字は必ず1にしています。
以上によりSFENによる任意局面の表記方法が定義されます。香落ち初期局面であれば、

lnsgkgsn1/1r5b1/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL w - 1

というように表記されます。

次に、指し手の表記について解説します。筋に関しては1から9までの数字で表記され、段に関してはaからiまでのアルファベット(1段目がa、2段目がb、・・・、9段目がi)というように表記されます。位置の表記は、この2つを組み合わせます。5一なら5a、1九なら1iとなります。
そして、指し手に関しては、駒の移動元の位置と移動先の位置を並べて書きます。7七の駒が7六に移動したのであれば、7g7fと表記します。(駒の種類を表記する必要はありません。)
駒が成るときは、最後に+を追加します。8八の駒が2二に移動して成るなら8h2b+と表記します。
持ち駒を打つときは、最初に駒の種類を大文字で書き、それに*を追加し、さらに打った場所を追加します。金を5二に打つ場合はG*5bとなります


GUIからエンジンに送られるコマンド

usi

GUIがエンジンを起動した時に最初に送るコマンドです。エンジンは、このコマンドを受信したらすぐにidコマンドを返し、必要に応じてoptionコマンドを返します。そして最後にusiokコマンドを返す必要があります。

isready

対局開始前に送ります。エンジンは対局準備ができたらreadyokを返すことになります。

setoption name <id> [value <x>]

エンジンに対して値を設定する時に送ります。
<id>で指定する名前は、エンジンが起動時にoptionコマンドで返した名前になります。value <x>で指定する部分は、文字列であればその文字列を入れ、チェックボックスのブーリアン値であればtrueまたはfalseになります。
将棋所2.8.0からは、エンジン設定ダイアログでOKを押したときの設定内容を将棋所の側で保存して、対局開始時に同じ内容をsetoptionで送るようになりました。そのため、エンジンがsetoptionの内容を初期設定ファイルに保存する機能は不要になりました。
また、USI_PonderとUSI_Hashに関しては、それぞれ対局ダイアログの「相手の手番中に先読み」と「ハッシュ」に対応しており、将棋所で対局を開始するときに必ず送るので、エンジンがoptionコマンドで指定する必要はありません。
以下に具体例を示します。

// オプション名USI_Ponderの値をtrueに設定
setoption name USI_Ponder value true
// オプション名USI_Hashの値を32に設定
setoption name USI_Hash value 32

usinewgame

対局開始時に送ります。これで対局開始になります。

position [sfen <sfenstring> | startpos ] moves <move1> ... <movei>

思考開始局面をエンジンに知らせるためのコマンドです。エンジンに思考を開始させる場合、positionコマンドで思考開始局面を送り、それに続けてgoコマンドを送って思考開始を命令することになります。
positionコマンドの書式として、まず初期局面を記述し、それに続けて初期局面からの全ての手を記述します。
初期局面の部分については、平手初期局面であれば単にstartposと書き、そうでなければsfenに続けてSFENの書式に基づいて記述します。
それに続く指し手の部分は、初期局面に続けてmovesを書き、さらに初手からの全ての手を並べて書きます。
例えば、平手初期局面から▲7六歩、△3四歩、▲2六歩と進んだ局面であれば、

position startpos moves 7g7f 3c3d 2g2f

となります。2枚落ち初期局面から△6二玉、▲7六歩、△3二銀と進んだ局面であれば、

position sfen lnsgkgsnl/9/ppppppppp/9/9/9/PPPPPPPPP/1B5R1/LNSGKGSNL w - 1 moves 5a6b 7g7f 3a3b

となります。このように、毎回毎回、初期局面からの全ての指し手を書く必要があるので、冗長に思われるかもしれません。しかし、この方式を採用することにより、エンジンは先読み機能への対応が簡単にできるようになります。また、この方式に対応した時点で、待ったの機能が自動的に実装済みになります。

go

思考開始の合図です。エンジンはこれを受信すると思考を開始します。
自分の手番の時に思考を開始することを通常思考と呼びます。相手の手番の時に思考を開始することを先読み思考と呼びます。後述しますが、go ponderによって思考を開始するときは先読み思考、ponderがついていないgoコマンドで思考を開始するときは通常思考となります。
以下に、goコマンドのオプションについて解説します。

ponder

これを使うときは、必ずgo ponderというように、goのすぐあとにponderを書くことになります。
ponderという言葉は、辞書では「熟考」と訳されていますが、思考ゲームにおいては、相手の手番中に次の手を考える「先読み」を意味します。
go ponderは、先読みを開始する合図となります。(先読みを開始すべき局面は、この前にpositionコマンドによって送られてきています。)
エンジンは、go ponderによって思考を開始する場合、GUI側から次のコマンド(stopまたはponderhit)が送られてくる前にbestmoveで指し手を返してはいけません。(たとえ、思考開始の時点で詰んでいるような場合であったとしてもです。)相手が手を指すと、それによってstopまたはponderhitが送られて来るので、それを待ってからbestmoveで指し手を返すことになります。(この辺の流れついては、後述する「対局における通信の具体例」を読んで下さい。)

btime, wtime <x>

先手と後手の残り時間を表示します。(btimeは先手の残り時間、wtimeは後手の残り時間。)単位はミリ秒です。
なお、byoyomiまたはbinc/wincで0より大きい値が設定されている場合、次の手には、残り時間とそれらを合計した時間まで考えることができます。詳しくは下のbyoyomiとbinc/wincの項目を参照して下さい。

byoyomi <x>

これはUSIの原案にはありませんが、将棋特有の秒読みに対応するために追加しました。単位はミリ秒です。先手と後手で秒読みの時間が違うということは想定していないので、どちらにも共通の値となります。
btime, wtime, byoyomiを使って、残り時間と秒読み時間を指定することができます。先手の残り時間が60秒、後手の残り時間が50秒、秒読みが10秒であれば、

go btime 60000 wtime 50000 byoyomi 10000

というようになります。この場合、次が先手番だとして、先手は次の手に残り時間60秒と秒読み10秒を合計した70秒まで考えることができます。

binc, winc <x>

フィッシャークロックルールで使われる、1手ごとの加算時間を表示します。単位はミリ秒です。このルールでは自分の手番が来るたびに持ち時間が加算され、先手はbinc、後手はwincで示される時間が加算されることになります。その加算時間内に手を指すと、余った時間は次の手の持ち時間に追加されます。
持ち時間なしで1手ごとの加算時間が10秒、双方とも10手ずつ指して先手の消費時間が60秒、後手の消費時間が50秒だとします。この場合、加算時間の総計は双方とも110秒になっているので、先手の残り時間は50秒、後手の残り時間は60秒となります。将棋所は次の指し手の思考開始コマンドを次のように送ります。

go btime 40000 wtime 50000 binc 10000 winc 10000

つまり、「先手の残り時間40秒、後手の残り時間50秒、先手の加算10秒、後手の加算10秒」の形で送ります。するとエンジン側では、次の手で先手は残り時間と加算を合わせて最大50秒考えることができ、次の手に進んだあとも1手につき10秒加算されることがわかります。
なお、秒読みと加算は、両方同時に使用することはありません。そのため、秒読みがあるときはbinc/wincは送らず、加算があるときはbyoyomiは送りません。ただし秒読みと加算が両方とも0ならbyoyomi 0を送ります。

infinite

時間無制限で思考させる場合に使います。(将棋所では、検討機能で制限時間を無制限にした時にgo inifiniteを送ります。)
エンジンはgo infiniteで思考を開始した場合、次にstopが送られてくる前にbestmoveを返してはいけません。stopが送られてきた時にbestmoveを返すことになります。

mate [<x> | infinite]

詰将棋解答を開始する時に使います。この時、制限時間を指定することができます。単位はミリ秒です。制限時間1分で解かせるのであれば、

go mate 60000

となります。また、時間無制限で解かせるのであれば、次のようにinfiniteを使います。

go mate infinite

エンジンは、go mateによって思考を開始した場合、checkmateコマンドを返すことになります。詰将棋解答に対応していないならcheckmate notimplementedを返すようにして下さい。

なお、USIの原案では、go mateのパラメータとして手数を指定することになっていて、go mate 9と指定すれば、9手以内に詰みがあるかどうか探索することになっています。しかし、チェスと違って将棋での詰手数というのは非常に長くなることがあり、詰将棋を解かせる時に「何手以内に詰みがあるかどうか」という使い方はほとんどしないので、手数の代わりに制限時間を指定するように変更しました。

stop

エンジンに対し思考停止を命令するコマンドです。エンジンはこれを受信したら、できるだけすぐ思考を中断し、bestmoveで指し手を返す必要があります。(現時点で最善と考えている手を返すようにして下さい。)
stopは通常思考と先読み思考のいずれの場合にも送られる可能性があります。通常思考では、人間対エンジンでエンジンの思考中に「急」(すぐ指させる)ボタンを押した場合と、検討を中断した場合に送ります。先読み思考ではエンジンの予想手が外れた場合に送ります。

ponderhit

エンジンが先読み中、前回のbestmoveコマンドでエンジンが予想した通りの手を相手が指した時に送ります。エンジンはこれを受信すると、先読み思考から通常の思考に切り替わることになり、任意の時点でbestmoveで指し手を返すことができます。

quit

アプリケーション終了を命令するコマンドです。エンジンはこれを受信したらすぐに終了する必要があります。

gameover [ win | lose | draw ]

gameoverというコマンドはUSIの原案にはありませんが、これがないと対局終了をエンジンに知らせることができないために追加しました。gameoverのあと、エンジンの結果に応じてwin, lose, drawのいずれかのパラメータも一緒に送られます。
エンジンはgameoverを受信したら対局状態を終了して、対局待ち状態になります。その後、isready及びusinewgameを受信すると次の対局開始ということになります。


エンジンからGUIに送られるコマンド

id name <program name>
id author <program author>

usiコマンドを受信した時に最初に送り返すコマンドです。この時、id nameでプログラム名を返し、id authorで作者名を返します。将棋所でエンジンを追加する場合、このid nameで返した名前を登録するので、必ず送り返す必要があります。

usiok

usiコマンドを受信した時に最後に送り返すコマンドです。将棋所ではこれを返さないエンジンはUSIエンジンと認識されず登録できないので、必ず送り返す必要があります。将棋所の場合、usiを送ってから5秒以内にusiokが返ってこないとタイムアウトしてしまうので、起動時にあまり時間のかかる処理をさせないように注意して下さい。

readyok

isreadyコマンドを受信した時、対局準備ができたらreadyokを返して下さい。対局前に時間のかかる処理をする場合など、isreadyを受信してからreadyokを返す間にやるといいと思います。

bestmove <move1> [ponder <move2>]

エンジンの指し手を返します。<move1>の部分にエンジンの指し手を記述します。
単に指し手を返すのであれば、bestmoveのあとにエンジンの指し手だけを追加し、ponderは追加しないようにします。エンジンが7g7fと指し、その後の先読みをしないのであれば、

bestmove 7g7f

となります。
指し手を返したあと、先読み機能を使いたいのであれば、自分の指し手のあと、ponder <move2>の部分に、エンジンが予想した相手の指し手を追加します。これがGUIに対する先読み要求になります。例えば、エンジンが8h2b+と指すとして、それに対する相手の指し手を3a2bと予想し、その局面からの先読みを要求するのであれば、

bestmove 8h2b+ ponder 3a2b

となります。この後、GUI側から、相手が3a2bと指した局面がpositionコマンドによって送られてきて、それに続けてgo ponderが送られてくるので、その時点から先読みを開始します。

このように、USIプロトコルにおいて、エンジンの先読みは、

エンジン側からbestmove <move1> ponder <move2>による先読み要求

GUI側からpositionコマンドで先読み思考開始局面の送信

GUI側からgo ponderコマンドが送られ先読み開始

という一連の流れに沿って行われます。この方式に従うことにより、先読みの実装が容易になります。また、エンジンの先読み時の予想手が将棋所の「予想手」の欄に表示され、先読み中の思考内容もinfoコマンドを使えば通常思考時と同様にGUIで表示できるようになります。

なお、先読みをする時に、予想手を一つではなく複数考えたいということがあるかもしれません。そのような場合は、USIの本来の使い方からは外れますが、bestmove <move1> ponder <move2>ではなく、単にbestmove <move1>だけを返し、相手の手番中に勝手に先読みするようにして下さい。

エンジンの投了について

USIの原案では、エンジンが投了する方法が用意されていません。しかし、エンジン側の判断で投了できないというのはどう考えてもおかしな話なので、投了する方法を追加しました。

bestmove resign

を送ることによって、GUIに投了を伝えることができます。GUIはこれを受信すると対局状態を終了し、gameoverコマンドをエンジンに送ります。
また、エンジンは、相手の指し手によって詰まされてしまった場合は必ずbestmove resignを返すようにして下さい。

入玉勝ち宣言について

入玉して勝ちと判断した時、エンジンは入玉勝ち宣言をすることができます。このための方法を追加しました。

bestmove win

を送ることによって、GUIに入玉勝ち宣言を伝えることができます。
GUIはこれを受信すると、通信対局であれば、通信相手に%KACHIコマンドを送ります。人間対エンジン、またはエンジン対エンジンであれば、その宣言が正しいかどうか、GUIが判断して勝敗を決めます。
入玉勝ち宣言が正しいかどうかは、CSAルールでの定義に基づくものとします。それ以外のルール(24点法など)は使用しません。

info

エンジンは、goコマンドで思考を開始してからbestmoveコマンドで指し手を返すまでの間、infoコマンドによって思考中の情報を返すことができます。infoコマンドはいくつかのサブコマンドで構成されます。以下に、そのサブコマンドについて解説します。
また、サブコマンドは1行にまとめて書くことができます。(ただし、pvとstringの同時使用は不可。)

depth <x>

現在思考中の手の(基本の)探索深さを返します。

seldepth <x>

現在、選択的に読んでいる手の探索深さを返します。seldepthを使うときは、必ずその前でdepthを使って基本深さを示す必要があります。基本深さが5で、選択的に読んだ手の深さが8であれば、

depth 5 seldepth 8

というように続けて書くことになります。

time <x>

思考を開始してから経過した時間を返します(単位はミリ秒)。これはpvと一緒に返す必要があります。

nodes <x>

思考開始から探索したノード数を返します。これは定期的に返す必要があります。

pv <move1> ... <movei>

現在の読み筋を返します。(pvというのは、principal variationの略です。)pvのあと、指し手を続けて書くことになります。なお、pvを使う場合、infoのあとに書くサブコマンドの中で最後に書くようにして下さい。stringとの同時使用はできません。

score cp <x>
score mate <y>

エンジンによる現在の評価値を返します。score cpで評価値を返す場合、歩1枚の価値を100とした値を返すことになります。(cpというのは、centi pawnの略です。)この値は、エンジンの側から見た値となり、エンジンが有利ならプラス、エンジンが不利ならマイナスの値になります。エンジンが50点有利と判断しているならscore cp 50となります。
エンジンが詰みを発見した場合は、score mateによって詰み手数を返すことができます。詰み手数に入れる数字は、エンジンの勝ちならプラス、エンジンの負けならマイナスになります。エンジンが6手後に詰まされて負けると判断した場合はscore mate -6となります。
ただし、「詰みを発見したが、手数がわからない」ということがあるかもしれません。(実は、サンプル用のエンジンであるLesserkaiが詰みを発見したときがこの状況になります。)こういう場合は、score mate + またはscore mate - のように、数字を使わず、単に+または-の記号を使用するようにして下さい。(これはUSIの原案にはありませんが、将棋所で機能追加しています。)

lowerbound

評価値が下限値(実際にはその値を上回る可能性がある)の場合に返します。

upperbound

評価値が上限値(実際にはその値を下回る可能性がある)の場合に返します。

lowerboundとupperboundを使う場合は、score cp <x> lowerbound または score cp <x> upperbound のように使って下さい。
この場合、将棋所では、評価値の隣の欄に++または--(lowerboundなら++、upperboundなら--)を追加して表示します。(表示設定の「対局または検討で、後手の評価値を反転表示」にチェックしてから対局または検討をした場合、あるいは棋譜解析の場合には、後手番のエンジンの++または--は反転表示されます)

currmove <move>

現在思考中の手を返します。(思考開始局面から最初に指す手です。)

hashfull <x>

エンジンが現在使用しているハッシュの使用率を返します。単位はパーミル(全体を1000とした値)になります。現在のハッシュ使用率が20%であれば、hashfull 200となります。
このコマンドは定期的に返す必要があります。

nps <x>

1秒あたりの探索局面数を返します。これは定期的に返す必要があります。

string <str>

GUIに表示させたい任意の文字列を返します。GUIはstringサブコマンド以降の文字列を全てそのまま表示します。将棋所の場合、この文字列は「読み筋」の欄に表示します。そのためpvと同時使用はできません。

これらのサブコマンドは次の例のように1行に並べて書くことができます。実際の使い方としては、pvを返すときに、time、depth、nodes、scoreなどをまとめて返すとよいでしょう。
また、定期的に返す必要のある、nodes、nps、hashfullなどもまとめて返すとよいと思います。(定期的に返す場合、あまり頻繁だと無駄なので、少なくとも1秒は間隔をおくようにして下さい。)

info time 1141 depth 3 nodes 135125 score cp -1521 pv 3a3b L*4h 4c4d
info nodes 120000 nps 116391 hashfull 104
info string 7g7f (70%)

option

エンジン固有の設定値を送ります。このコマンドは、GUIからusiが送られてきたあと、idとusiokを送り返す間に送ることになります。GUIはこれによって送られた内容を読み取り、エンジン設定ダイアログで表示することができます。エンジン設定ダイアログでOKを押すと、設定した内容をsetoptionコマンドでエンジンに送ることになります。optionコマンドは以下の書式になります。

option name <optionname> type <optiontype> <parameter...>

optionnameにオプション名を入れ、optiontypeにオプションの種類を入れます。optionnameにはスペースを入れてはいけません。

オプション名については、USIによって予約されているものがいくつかあります。そのうち、USI_HashとUSI_Ponderについては、将棋所で対局を開始するときに必ずsetoptionコマンドで値を送るようにしているので、エンジン側で独自に値を保存する必要はありません。この2つのオプションについて解説します。

<id> = USI_Hash, type spin

エンジンのハッシュメモリの量を指定します。単位はMBになります。

<id> = USI_Ponder, type check

エンジンが先読み機能を使用できるかどうか指定します。これでfalseを指定すると、エンジンは先読み機能を使うことはできません。

なお、将棋所で対局開始時にこの2つを必ず指定しているのは、この2つは使用頻度が高く、値の変更も頻繁に行われると思われるので、いちいちエンジン設定ダイアログを開かなくても設定できるようにしたためです。
USIの原案では、これ以外にも、USI_OwnBook、USI_MultiPV、USI_ShowCurrLine、USI_ShowRefutations、USI_LimitStrength、USI_Strength、USI_AnalyseModeという名前のオプションが予約されています。(詳しくは原案を読んで下さい。)
ただし、将棋所では、これらのオプションを設定することはありません。

オプションの種類は以下の6種類があります。このオプションの種類により、エンジン設定ダイアログで表示されるコントロールの型が決まります。

check

チェックボックスを表示します。

spin

数値のみを入力できるコントロールを表示します。

combo

ポップアップメニューを表示します。

button

ボタンを表示します。このボタンを押すと、オプション名で指定されたコマンドがエンジンに送られます。(オプション名がoptionnameなら、このボタンを押すと、setoption name optionnameというコマンドが送られます。)

string

文字列を入力できるコントロールを表示します。

filename

ファイル名を入力できるコントロールを表示します。ファイル名を指定しやすいよう、ファイル選択ボタンを表示し、それを押すと、ファイル選択のダイアログを表示するようになっています。ここで選択したファイルの絶対パスが設定値となります。

これらの種類を指定した後、そのデフォルト値や、入力値の範囲などを指定することができます。

default <x>

デフォルト値を指定します。種類がcheckであれば、trueまたはfalseとなります。種類がspinであれば数字、combo、string、filenameであれば、任意の文字列になります。
なお、stringまたはfilenameでデフォルト値が空の文字列の場合は<empty>を指定して下さい。(emptyの両側に不等号の記号が必要です。)

min <x>
max <x>

種類がspinである場合、その値の下限値と上限値を指定します。

var <x1> var <x2> ...

種類がcomboの場合、選択できる文字列を追加します。

以下に、optionコマンドの使用例を示します。

// オプション名がUseBook、種類がcheck、デフォルト値がtrueであれば
option name UseBook type check default true

// オプション名がSelectivity、種類がspin、デフォルト値が2で、選択可能な値が0から4までなら
option name Selectivity type spin default 2 min 0 max 4

// オプション名がStyle、種類がcombo、デフォルト値がNormalで、選択可能な文字列がSolid、Normal、Riskyの3つであるなら
option name Style type combo default Normal var Solid var Normal var Risky

// オプション名がResetLearning、種類がbuttonなら
option name ResetLearning type button

// オプション名がBookFile、種類がstring、デフォルト値がpublic.binなら
option name BookFile type string default public.bin

// オプション名がLearningFile、種類がfiliename、デフォルト値が空なら
option name LearningFile type filename default <empty>

checkmate [<move1> ... <movei> | notimplemented | timeout | nomate]

checkmateというコマンドはUSIの原案にはありませんが、GUIからgo mateを送られて詰将棋解答を開始したあと、その結果を返すためのコマンドとして追加しました。checkmateのオプションは以下の通りになります。

notimplemented

詰将棋解答機能に対応していないエンジンの場合、go mateに対しては
checkmate notimplementedを返します。

timeout

制限時間ありで詰将棋解答を開始した場合、制限時間内に結論が出なければ、
checkmate timeoutを返します。

nomate

詰将棋を解いて、「この問題は詰まない」という結論が出たら、
checkmate nomateを返します。

詰将棋を解いて、その問題が詰むのであれば、その手順をcheckmateのあとに続けて書きます。例えば、

checkmate G*8f 9f9g 8f8g 9g9h 8g8h

というようになります。詰将棋解答時の全体の流れについては、後述する「詰将棋解答における通信の具体例」の項目を参考にして下さい。

なお、「詰将棋解答機能だけに対応して、通常の対局に対応していない」というエンジンを作った場合は、(go mateでない)通常のgoコマンドに対してはbestmove resignを返すようにしておいて下さい。間違ってそのエンジンで対局を開始してもすぐに対局が終わるので、そのエンジンでは対局できないことがわかります。


対局における通信の具体例

以下に、実際の通信の具体例を示します。特に、思考開始と指し手について解説します。なお、GUIがエンジンに対して送るコマンドの前には">"を、エンジンがGUIに対して送るコマンドの前には"<"をつけています。

エンジン起動から対局開始まで

// エンジン起動
>usi

// usiコマンドに対する返答(例)
<id name Lesserkai
<id authoer Program Writer
<option name BookFile type string default public.bin
<option name UseBook type check default true
<usiok

// 対局開始前のオプション設定(例)
>setoption name USI_Ponder value true
>setoption name USI_Hash value 32
>setoption name BookFile value public.bin
>setoption name UseBook value true

// 対局開始前の準備
>isready
<readyok

// 対局開始
>usinewgame

指し手のやり取り

最も重要な部分である、指し手の部分について説明します。(なお、以下の例で、goコマンドのオプションである持ち時間指定部分は省略しています。)
まず、GUIはエンジンに対し、positionコマンドで現在局面を送り、それに続けてgoコマンドを送って思考開始を命令します。エンジンが後手で、先手が平手初期局面から7七歩と指した局面であれば、

>position startpos moves 7g7f
>go

それに対しエンジンは、思考したあと、bestmoveコマンドで指し手を返します。先読みしないのであれば、エンジンの指し手だけを返します。

<bestmove 3c3d

なおエンジンは、goを受信してからbestmoveを返すまでの間に、infoコマンドで思考内容を送ってGUIに表示させることができます。(この例では省略しています。)

次に、先読み機能を説明します。
エンジンが後手で、先手が平手初期局面から1六歩と指した局面であれば

>position startpos moves 1g1f
>go

エンジンはbestmoveコマンドで指し手を返しますが、この時に先読み要求を出すことができます。エンジンの指し手が4a3bで、それに対する相手の指し手を6i7hと予想したのであれば

<bestmove 4a3b ponder 6i7h

GUIはこれを受信すると、すぐにpositionコマンドで思考開始局面を送ります。この局面は、現在局面に、エンジンが予想した相手の指し手(この場合は6i7h)を追加したものになります。それに続けてgo ponderコマンドを送ります。

>position startpos moves 1g1f 4a3b 6i7h
>go ponder

エンジンはこれを受信すると先読みを開始します。goコマンドの解説にも書きましたが、go ponderによって先読みを開始した場合、次にGUIからstopまたはponderhitが送られてくるまで、エンジンはbestmoveを返してはいけません。相手が次の手を指す前に思考が終わったとしても、GUIからstopまたはponderhitが送られてくるまで待つことになります。

やがて、相手が手を指します。その手がエンジンの予想手と一致した場合と、そうでない場合で動作が異なります。

エンジンの予想手が外れた場合

この場合、GUIはエンジンにstopを送ります。

>stop

エンジンはこれに対し、思考中ならすぐに思考を打ち切って、現時点で最善と考えている手をbestmoveで返します。既に思考が終わっていたなら、探索済みの指し手をbestmoveで返します。(bestmoveのあとにponderで相手の予想手を追加しても構いませんが、いずれにしろ無視されます。)

<bestmove 6a5b ponder 4i5h

この、stopに対してbestmoveで返された指し手は、外れた予想手(この場合は6i7h)に対する指し手なので、GUIはこの内容を無視して、正しい相手の指し手(現在局面)を送ります。続けてgoコマンドも送ります。相手が7g7fと指したのであれば

>position startpos moves 1g1f 4a3b 7g7f
>go

エンジンはこれによって通常の思考を開始します。

エンジンの予想手が当たった場合

この場合、GUIはエンジンにponderhitを送ります。

>ponderhit

予想手が当たったので、エンジンは引き続き思考を継続して構いません。既に思考が終わっていたら、すぐにその指し手を返すこともできます。bestmoveで指し手を返すとき、前回と同様にponderを追加して先読み要求を出すこともできます。

<bestmove 6a5b ponder 4i5h

以下、同様にして対局が継続されます。

対局終了

エンジンは、自分の指し手のとき、bestmove resignを送ることで投了することができます。また、相手の指し手によって詰まされてしまった場合は、必ずbestmove resignを返すようにしてください。

<bestmove resign

対局終了を確認すると、GUIはエンジンにgameoverコマンドを送ります。エンジンが勝った場合はgameover win、負けた場合はgameover loseを送ります。千日手が発生した場合は、gameover drawを送ります。

>gameover lose

エンジンはこれで対局状態を終了し、次の対局待ち状態になります。


詰将棋解答における通信の具体例

詰将棋解答についても、全体の流れとしては対局時とほとんど同じです。エンジン起動から解答準備に入るまでのコマンドのやり取りは、USI_Ponderの設定をしないことを除けば、通常の対局時と同じです。(対局ではないので、usinewgameとか不要に思われるかもしれませんが、対局時と同じような流れにした方がエンジンの詰将棋対応をやりやすいと思ったので、あえて同じようにしてあります。)

// エンジン起動
>usi

// usiコマンドに対する返答(例)
<id name Lesserkai
<id authoer Program Writer
<option name BookFile type string default public.bin
<option name UseBook type check default true
<usiok

// 詰将棋解答開始前のオプション設定(例)
>setoption name USI_Hash value 32
>setoption name BookFile value public.bin
>setoption name UseBook value true

// 詰将棋解答開始前の準備
>isready
<readyok

// 詰将棋解答開始
>usinewgame

問題と解答のやり取り

次にGUIは問題局面を送って詰将棋解答の開始をエンジンに命令し、エンジンは解答を返します。この部分のやり取りも通常の対局時と似ています。通常の対局時にはGUIがgoを送ってエンジンが思考を開始し、エンジンはbestmoveで指し手を返しますが、詰将棋解答時はgoの代わりにgo mateを送ってエンジンが思考を開始し、エンジンはbestmoveの代わりにcheckmateを返す、ということになります。

まずGUIはpositionで問題の局面を送ります。例えば、

>position sfen 9/9/9/9/9/k8/9/9/1R2K4 b Gr2b3g4s4n4l18p 1

positionに続けてgo mateコマンドを送ります。時間無制限で解かせるのなら、

>go mate infinite

これでエンジンは思考を開始し、checkmateコマンドを返します。

<checkmate G*8f 9f9g 8f8g 9g9h 8g8h

なお、go mateを受信してからcheckmateを返すまでの間、エンジンはinfoコマンドを使って思考内容を返すことができます。

エンジンはcheckmateを返したら次の問題待ちになります。そして、またpositionとgo mateが送られてきたら、次の問題の解答を開始することになります。


USIに追加されたコマンド

既に説明しましたが、USIの原案にないコマンドで、USIに新しく追加されたコマンドなどについてまとめます。

GUIからエンジンに送るコマンド

gameover
goのオプションとしてbyoyomi
また、追加ではありませんが、go mateのパラメータを原案から変更しています。

エンジンからGUIに送るコマンド

bestmoveのパラメータとしてresignとwin
checkmate

USIの原案のうち、未対応のコマンド

将棋所では、USIの原案にあるコマンドのうち、次のコマンドなどに未対応です。今後の対応も未定です。

GUIからエンジンに送るコマンド

debug
register
goのオプションのうち、searchmoves, movestogo, depth, nodes, movetime

エンジンからGUIに送るコマンド

registration
infoのサブコマンドのうち、multipv, currmovenumber, cpuload, refutation, currline


ホーム>USIプロトコルとは