stopコマンドでbestmove返すな問題

stopコマンドに対してbestmoveを返さないのはUSIプロトコルで規定されているのでしょうか?

疎結合クラスター化のプログラムなどを書いているとよくこのことが問題となります。

USIプロトコルの説明には、この部分が明示的に書かれていないため、実装依存の問題かと解釈する人がおられるかと思います。

これは思考エンジンの実装依存の問題ではないです。USIプロトコル上、goコマンドに対してbestmoveは一度しか返してはならないのです。

tanuki-さんほどの敏腕プログラマーが勘違いしてしまうぐらいですから、誰もがハマる問題だと言えると思いますが、タイミングチャートを書いてみると一目瞭然です。

いまstopに対しても(常に)bestmoveを返すと仮定してみましょう。

このとき、goによる探索が終了してbestmoveを返すのと入れ違いにstopが送られてきた時にbestmoveを二重に返すことになります。

ホスト側からはstopに対して1つ目のbestmoveが返ってきたように見えるので次のposition〜goコマンドを送りますが前回の2つ目の(stopに対する)bestmoveを遅れてこの局面のbestmoveとして受け取ってしまいます。それは前の局面のbestmoveなので当然この局面では不適切な指し手となっています。

このように、USIプロトコル上、stopに対してbestmoveを返す仕様だと解釈することは不可能なのです。(そう実装すると上記の不具合が出るため) bestmoveは送られてきたgoの回数だけしか返してはならないと解釈しなくてはなりません。

この記事が、疎結合クラスター勢の参考になれば幸いです。

stopコマンドでbestmove返すな問題” への4件のコメント

  1. 謎手を出す癖があって、それで弱くなっていた原因がこの解釈の差でした、というチームがどのくらいあったのか、私、気になりますw

    • 大会では、サーバーからはgoコマンドで残り時間が送られてくるだけなので(サーバー側からはstopは送られてこないので)、大会では影響ないでしょうね。

  2. 「あから」の時もこれは問題になり stop でbestmoveを返すのは go を受け取った回数よりbestmoveを送った回数が少ないときだけ、としていました。

    if ( ! strcmp( token, “stop” ) ) {
    if ( is_ignore_stop()==0 ) {
    send_latest_bestmove();
    }
    return 1;
    }

    int is_ignore_stop()
    {
    if ( usi_go_count <= usi_bestmove_count ) return 1; // このstopは無視
    return 0;
    }

    • 標準入力の監視用のスレッド側でbestmoveを返すという作りにするのであれば、そうなりますね。
      Stockfishのようにstopに対してbestmoveを返すのではなく、goに対する探索終了でbestmoveを返すコードのほうがわかりやすいような気も。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です