うらお今回は、デバッグ用のUSI拡張コマンドの説明から、段・筋・升まで。“user”やねうら王miniではUSI拡張コマンドとして”user”というコマンドを追加してある。これを用いると、user.cppというファイルの次の関数が呼び出される。USI拡張コマンド"user"が送られてくるとこの関数が呼び出される。実験に使ってください。USI拡張コマンド"user"が送られてくるとこの関数が呼び出される。実験に使ってください。pos;}この関数をユーザーに開放してある。間、ここを用いてやねうら王miniの指し手生成などの機能について説明をしていく。初期局面の表示さきほどuser_test()のなかでコメントアウトしてあった部分を有効にしてみよう。いうような概念である。「局面」と「盤面」とこの意味において使い分けることがある。「盤面」に手駒や手番を含めることもある。そのへんは前後の文脈から理解してもらいたい。pos;}この状態でやねうら王miniをビルドして、起動して、”user”コマンドを入力するとさきほどと同様に平手の初期盤面が表示される。ここで見て欲しいのはPositionというのは現在の局面が格納されているクラスである。うら王miniでは、ほとんどすべてのenum、クラスに対してストリーム演算子へのリダイレクトを定義してある。ようにすれば、標準出力に表示できるということである。基本的には、このとき、USI形式で出力する。USIプロトコルで用いないものに関しては、独自の形式で出力する。posには現在の局面(起動時には平手の開始局面)が入っているので、標準出力に平手の開始局面が出力されたわけである。手番は、ソースコード上、次のように書いてある。0,};このへんは、Stockfishに倣っている。先手が黒(BLACK)、後手が白(WHITE)なので、手番は色(Color)だということのようである。うら王miniでは、このソースコードで学習した学習者が、AperyやStockfishのソースコードを読もうとするときに苦難なく進めるように配慮し、なるべく関数名などをAperyとStockfishに合わせてある。AperyとStockfishとで呼び名が異なる場合は、Stockfishに倣うようにしてある。教育的な配慮をするのも、なかなか大変である。手番の表示テストさきほど書いたようにやねうら王miniではほぼすべてのenumに対してストリーム演算子での出力をサポートしている。試しに手番が正しく表示されるかどうか調べてみよう。~()は、手番を反転させる。先手なら後手に、後手なら先手になる。enumについているZEROとNBについてさきほど、COLOR_NBとCOLOR_ZEROという定数が定義されていた。これらは配列を宣言するときや、ループにおいて用いられる。array[COLOR_NB];例えば、次のようなループ。}このようにほとんどのenumにはXXX_ZEROという定数とXXX_NBという定数が定義されている。・配列が宣言しやすい・ループを書きやすいということである。「ループを書きやすい」については説明を要するかも知れない。将棋プログラムにおいては、enumのレイアウト(定数の順番)を変更したりしたいことが多々ある。いま、BLACKは0であるが、これをBLACKを1に変更した場合、どうだろうか。このとき、次のようにループを書いていたのでは、意図通りループを回らなくなってしまう。}ゆえに、forで要素すべてに対して何らかの処理をしないといけないような場合、XXX_ZEROとXXX_NBを用いて回る必要があるのだ。enumに対する演算子について上のように定義されたenumに対してインクリメントやデクリメント、加減算をしたいとこは多々ある。そのときに、都度、型のcastが発生するのは面倒くさい。そこで適切にoperatorを定義すべきであるが、すべてのenumに対して定義するのは面倒くさい。そこで、Stockfishに倣い、enumに対して次のようなマクロを用いて一括してoperatorを定義してある。enumで定義されている型に対して用いる。Stockfishのアイデア。enumで定義されている型に対して用いる。Stockfishのアイデア。}ENABLE_OPERATORS_ON(Color)ENABLE_OPERATORS_ON(File)ENABLE_OPERATORS_ON(Rank)ENABLE_OPERATORS_ON(Square)...本来ならばstrong_typedefのような形名を作り出すためのtypedefを使うべきなのだが、C++11には存在しないので仕方がない。上のようなoperator定義マクロで凌ぐのは、わりと現実的でかつ、シンプルなソースコードになるようである。筋と段は次のように定義されている。筋はFile、段はRankと呼ぶ。これはチェスの流儀に従っている。FILE_3なら3筋。RANK_4なら4段目。FILE_3なら3筋。RANK_4なら4段目。0};盤面上の升目はSquare型として次のように定義されている。盤上の升目に対応する定数。以下、盤面の右上から左下までの定数。どの升であるかが表示されることに価値がある。盤上の升目に対応する定数。以下、盤面の右上から左下までの定数。どの升であるかが表示されることに価値がある。このレイアウトはAperyに倣っている。Aperyでは、Stockfishに倣い、RANK_1が9段目を表すので、上の定義とは、上下逆のように見える。「AperyのRankの定義は(Stockfishに倣ったものだと思うけど)、わかりにくいので修正したほうがいいのでは」と平岡さんに言ったら、「いま修正を考えてます」とのことだった。平岡さん、この件、修正されたようです。将棋の筋と段に合わせました。user2h2筋と8段目を合成したので、sqは盤面の2八の升を指すはずである。実行すると、2hと表示された。これはUSIプロトコルでの表示である。USIプロトコルでは、段をアルファベットで表す。1段目ならa、2段目ならb、...、8段目ならh、9段目ならiというわけである。2hとは2八の升を表すので、これはこれで正しく動作していることがわかる。<<()は、USIプロトコルで表示するときのために、USI表記の文字列を表示させるようになっている。ほとんどの場合において升目はこのように表示させているので、この升目表現に早く慣れて欲しい。()では第一に考えて出力するわけであるが、人間に見た目わかりやすい表現も別途用意している場合がある。次のようにしてみよう。user2八このように、pretty()という関数が定義されている場合、それはenumの内容を人間に少しだけわかりやすい形式で表現する。<<()が、pretty()の代わりとなっている。<<()で表示することをお勧めする。USI形式に慣れていない人への救済策としてpretty()があるだけなのだから...。enumに対するメンバー関数についてenumはメンバー関数を持てない。scopeに関数を置くしかない。Rankのenumのメンバー(的なもの)については、rank_XXXという名前にしてある。userhここまでのまとめ以上で、やねうら王miniではclassやstructではなくほとんどの場合においてenumが基本構造体の代わりと成すことがわかったと思う。これはこれで合理的な側面もあるので、慣れてもらいたい。:すごい作りこんでますね。その情熱のコピーください。生半可な覚悟ではできなそうだ。自分は探索部に非常に興味があって、どうやって1Mnpsとかって数字になるかが気になっています。それは置いといて、屋根さんの妙技が詰まったソースを早く読みたいです。