コンピューター将棋のために、長い利きのライブラリを作りました。
とても複雑な代物なので忘れないうちにざっと書いていきたいと思います。
Long Effect Libraryのソースコード
やねうら王miniのプロジェクトに含まれています。
https://github.com/yaneurao/YaneuraOu
長い利きとは?
まず、長い利きというのは、通常の利きとどう違うのかというところから。
将棋には香、角、飛車(+馬・龍)は、遠くまで利きます。このように遠くまで利く利きを長い利きと言います。
角と馬の長い利き
角と馬で長い利きは実は同じです。馬の上・下・左・右への利きは短い利きで、長い利きではないからです。同じく、飛車と龍も長い利きは共通です。
香の長い利き
また香は成ると長い利きを持っていません。
つまり、長い利きという観点で見たとき、将棋には、香、角=馬、飛車=龍という3種類のがあることになります。香は先後非対称(先手は上方向の長い利き、後手は下方向の長い利き)なので、これを分けて考えると4種類の長い利きの駒があると言えるでしょう。
何故長い利きが必要なのか?評価関数に必要なのか?
評価関数で長い利きは実際には使われることはないでしょう。評価関数で使いたいのは各升での利きの数です。じゃあ、何のために長い利きが必要になるのかということなのですが、これには2つの役割があります。
まず、利きの数の更新をするために長い利きを管理していると利きの数の更新が楽になるということがあります。
例えば、金を打つときに、その打つ升に長い利きがかかっていなければ金の利き(の数)だけを更新すれば利きの更新が完了します。将棋では打つ指し手は比較的多いので、利きの数の更新がとても楽になります。
利きの数の更新が楽になるということは利きの数を使った評価関数の差分更新がとても楽になるということで、『技巧』なんかはこのテクニックを用いています。
長い利きをどういうデータ構造で持つか
長い利きの特徴として同じ方向に重複して利かせることは出来ないというのがあります。香を2段ロケットのように重ねても、下側の香の利きは次の香の升で途切れていることになります。
このように利きが重複しないという特徴があるので、方角は8方向ありますから、長い利きは8bit(1バイト)で持つと良さそうです。すなわち、各升1バイトとなり、81升で81バイト、先後合わせるとこの倍というように持つことが考えられます。つまりByteBoardを2つ持つやり方です。
ところが、これはあまり良くないのです。
何故、長い利きの管理はByteBoardでは駄目なのか
この理由を説明するには、長い利きの更新について解説しなければならなくて、その説明がとても長くなるので、結論だけ先に書くと、長い利きは先後で2バイトを1組として、81升分持つほうが良いです。すなわち、WordBoardがベストだと私は思います。
この理由は次回説明します。
長い利きがあるもうひとつのメリット
長い利きを持っていると利きの数の差分更新が捗るという以外に、1手詰め判定が高速化できるというのがあります。
これについてもかなりの説明を要するのですが、一度には書ききれないので何回かに記事を分けて説明します。
つづく
>とても複雑な代物なので忘れないうちにざっと書いていきたいと思います。
これは本当に大切なこと。
そうして、何度も痛い目を見ないと身に付かないスタンスであります。
・・・ということは、やっぱり何度も痛い目を経験されておられる、、、のでしょうね。