検索で飛んでくる人用に簡単に書いておくと,2017年将棋電王トーナメントで相手考慮時間において指し手予測を複数行うことで自分の手番で時間をあまり使わずに対応するエンジンを作り準優勝した。キーワードがPonder,本手法をMulti Ponderと命名している。
元ネタは単なる思い付きで全着手ノータイムのおもちゃを作りたかったからだ。
時間管理(チェスでtime control)はチェス由来のフィッシャールールが適用されることが多い。本家(チェス界)では知らないが以下はコンピュータ将棋界のルールで説明する。
持ち時間5分一手10秒加算というのがfloodgateのルールである。世界選手権は持ち時間15分一手5秒加算,電竜戦では持ち時間10分一手2秒加算と皆諸事情あって異なっている。floodgateも元は選手権由来であるらしい。
http://wdoor.c.u-tokyo.ac.jp/shogi/floodgate.html
持ち時間を過ぎたら負けであるから,floodgateルールだと初手で5分であると思われがちなのだが初手から5分10秒使える。これは囲碁将棋などの秒読みルールからの転用が理由だと言われている。フィッシャールールでは指す毎に時間加算とあるから間違っている気もするが現行のプログラム実装を優先する。
実はやねうら王も随分の間(少なくとも2017,2018年頃)この加算分を使っていなかった。常に余裕を残していたのだが今はこれを加算するようになっている。つまり現在ギリギリの設定である。
で,順が後になったが探索エンジンとの通信に用いられるUSIプロトコルである。各方面で問題点を指摘されているが,ここではPonderの件についてだけにしておく。
USIプロトコルでは盤面の設定にpositionコマンド,探索実行にgoコマンドを用いる。
通常は問題ないが,Ponder時はgo ponderで探索実行開始する。Ponder手が当たればponderhitコマンドを送り探索を継続するし,外れればstopコマンドで停止させ再度goコマンドを送る。goコマンドの引数に持ち時間を与える。
ちなみにネット対戦で用いられるCSAプロトコルでは着手毎に使用時間が返ってくるためにそこから毎回持ち時間が逆算可能である。
USIプロトコルのどこに問題があるか?
ponderhitのタイミングである。go ponder時に持ち時間を入れる。相手が考慮して指し手を送る,受け取ったらそれでponderhitとしてエンジンに送る。ponderhit時には時間情報を送らない。
つまり,エンジン側は相手の考慮時間をどのくらい消費したかエンジン内でカウントする必要があるのだ。具体的に言うと,ponderhitが少しでも遅れればエンジン側からすれば相手の考慮時間が消費されたと考え,自分の考慮時間が消費されたことに気付かない。エンジン側からすれば悠々時間切れとなる。
ponderhitに引数はないので,プロトコル上補正する手段は無い。
go ponder中はponderhitコマンドのタイミングに対してシビアな状況であるにも関わらず探索中の情報もリアルタイムで出力されているため,それらの処理も必要となる。
まぁ,そういった僅かな差であるが数手蓄積されると時間切れになるらしい。やっと修正できたので時間切れの負けがなくなった模様。
実際ギリギリまで時間を使っていることを確認している。(test06側)
test06 vs. Kristallweizen_R9-3950X (2022-02-09 08:00)
以下,追記予定。
ーーー
某所で話題になっていたが,ponder中にstopやponderhitではなく突然gameoverが飛んでくる場合がある。(先手番の)max movesの場合と(相手番での)千日手の場合である。将棋所の方で一度stopを入れてもらえないかと以前打診したが仕様なので変更しないと回答頂いた。stopある方が無難なのだが仕様ならしようがない。
---
さらに追記。というか本体。
csa_usi_bridge_4fg.py · GitHub
floodgateで連戦するためのスクリプト。
上記のややこしい話に加えて対戦相手がマッチしなかった場合にタイムアウトして再接続待機部分が大きな変更。
ただし,その際に用いたtimeout_decoratorのためにWindowsのPythonで動かないことになった。まぁ,Windowsなら将棋所使いましょう。