まぁ、最後のやつはほんとに目標で、達成できるのはいつになることか…。達成できる時には決勝まで進んでいるのかも知れない。
まずは、反省を生かして、延長のパラメータをいつでも変更可能なように、マクロにした。例えば、先手と後手で違うパラメータで対戦させてテストができるように、コード上は、以下のようにした。
#define TORIAI_ENCHOU (teban==sente ? 5:0) int EnchouTotal=0; if (TORIAI_ENCHOU!=0) { EnchouTotal+=TORIAI_ENCHOU: } : : if (EnchouTotal!=0) { //EnchouTotal分だけ最大深さを増やして再探索 }
で、とりあえずは、全く延長しないことにして、いろいろと実験をすることにした。
…、そして、最後まで、
これは、昨年の鈴木将棋でバランスを崩したことから、延長の効果と延長した場合に余分にかかる時間のバランスを取る作業に難しさを感じていたからである。調整に時間が十分取れるなら、山下さんが提唱する0.5手延長や、私が現在考えている、現在の局面の評価値とα値との差と、手の評価値とによる深さの制御を行ってみたい。
鈴木将棋では、手の生成と評価について、以下の方法で行っていた。
この方法には色々と欠点があるが、欠点に付いては後述する。
さて、実は、鈴木将棋開発の際には、チェスの手法=枝刈なしでやってみる、という目標があった。これは、ハードの進歩の速度によって、チェス的な手法で十分強い将棋プログラムが出来る日が近い将来にやってくるであろう、との見込みから来たものであった。
そのため、手の評価についてはこのような簡易な実装になっていたのである。
しかし、色々と実験を繰り返して見たり、2000年の大会での結果を振り返った結果、「現在のコンピュータ将棋で一番大事なのは、どのように枝刈するかである」との結論に私は至った。
ここで、鈴木君は、その将棋の強さを生かして、
さて、うさぴょんの手の評価でまず試してみたのは、「今までの方法で、今まで以上に過激に枝刈しておき、先読みの過程の中で『良い』と評価された手を、親局面へ良い手として伝搬して、探索するべき手に加えていく」という方法である。一種の共有探索(「コンピュータ将棋の進歩」参照)であるといえる。
この方法は、そこそこ優秀で、同じ思考時間ならば、鈴木将棋に対して6割〜7割程度の勝率を得られるようになった。
ここで、このような結果から考えてみると、元々、鈴木将棋の実装では、一手指してみてその局面の評価値で手をソートしていたのであるが、そこに先読みの要素が全くないのが問題であろうと思われた。
鈴木将棋の局面の評価値は、基本的には駒割と駒の位置の評価、玉の周囲の利きの評価だけであったので、そのまま手の評価に使ってしまうと、例えば、敵の駒にあたりをかける手や、取られそうな駒に利きを付ける手などが高く評価されない。
そこで、手を評価する評価値が、何らかの先読みの要素を含んでいれば、おそらく優秀な手の評価が可能であると考えた。この時、考えたのが、交換値を利用した手の評価であった。自分の駒における交換値(取り合いでどれだけ損をするか)を下げ、相手の駒における交換値(そこでどれだけ得するか)を上げる手が良い手であると考えた。
この方法は以前の方法と比較して非常に優秀で、以前のバージョンと対戦した場合、8割以上の勝率をあげられるようになった。
後に、コンピュータ将棋の進歩3を読んだところ、金沢将棋の指し手の生成がほとんど同じアイディアに基づいた方法であることが分かり、驚いたとともにこの方法に対して自信を深めた。また、金沢氏の方法を参考に、交換値を評価しただけでは上位に来ないことのある、攻撃的な手も上位に来るように順位付けするよう、さらに改良した。これにより、以前のバージョンにほぼ負けなくなった。
ところで、現在の方法の問題点であるが、とにかく「手の評価」が遅い。
どれくらい遅いかと言うと、PentiumIIIの1GHzを用いても、
ここで、可能な全ての指し手を生成することも遅い原因の一つであると考えられるので、あまりにひどそうな手は手の評価をする前に枝刈することなどを検討した方が良さそうだ。
当初、以下のような局面で、先手の6六角打ちがまったく好手として認識されなかった。
後手の持駒:角1歩1 9 8 7 6 5 4 3 2 1 +---------------------------+ |v香 ・ ・ ・ ・ ・ ・v桂v香|一 | ・v飛 ・ ・v金v玉 ・v金 ・|二 | ・ ・v桂 ・v歩v歩v銀 v歩|三 | ・ ・v歩v歩v銀 ・v歩 ・ ・|四 |v歩v歩 ・ 歩 ・ 歩 ・ ・ 歩|五 | ・ ・ 歩 ・ 銀 ・ 歩 ・ ・|六 | 歩 歩 銀 ・ 歩 金 桂 ・ ・|七 | ・ 玉 金 ・ ・ ・ ・ 飛 ・|八 | 香 桂 ・ ・ ・ ・ ・ ・ 香|九 +---------------------------+ 先手の持駒:角1歩1
6六角を後手が放置すると、飛車で2二の金を取った後、同銀と飛車を取り返すと、同角成と進んで、飛車と金銀の二枚替え、さらに馬ができる、ということを理解できなかったのである。
このような場合には、角の影の利き(3三の銀が2二に動くと、その地点に角も利いて来ること)を考慮する必要がある。現在では、交換値の評価の中で、このような相手駒の利きを考慮して、角打ちが好手であることを認識できるようになっている。
また、飛車を香の前と後どちらから打つのがより良い手か、といった問題もある。
例えば、後手がどうあがいても1筋をすぐに突破できることが確定しているような場合には、香の前に飛車を打って、香車の利きがある状態で飛車を成りこんだ方が良いこともあるだろうし、1筋をすぐに破ることの出来ない場合、香の後ろから飛車を打ち、利きを足していきながら駒得を図ることが良い場合もある。
コンピュータ将棋の進歩2によれば、YSS7.0では、交換値の計算の際に、そのマスに利きのある一番安い駒から交換を進めるという単純なアルゴリズムを採用しているとのことだが、このような処理では、飛車を香の前後どちらから打っても交換値は同じになってしまう。手の生成にも交換値を用い、さらに末端では局面の評価にも交換値を用いるうさぴょんの方式では、このような問題を放置すると、手の生成・局面の評価を誤り、致命的な結果を招きかねない。
そこで、うさぴょんでは、交換値を求める際に、基本的には安い駒から交換を起こすのだが、飛び利きであったら前後の関係を考慮して交換の順序を入れ換えるような措置を行っている。これにより、香の前後のどちらに打つのか、正しい位置に飛車を打ち込むことが出来るようになっている。
前の節でも少し触れたが、うさぴょんでは、交換値を末端局面の評価にも用いている。せっかく交換値を毎回、毎マス計算(と言っても差分計算なのだが)するようにしたので、探索の末端においても交換値を用いて局面を評価することにしたくなったのだ。
これには、色々な方法が考えられるのだが、KFEndの方法を参考に、末端局面で先読みを延長し、以下のように評価することとした。
この方法はそこそこ現実的?らしく、うまく働いているようであるが、交換値の計算が正確でないととんでもないことになるのが問題といえば問題である。例えば、うさぴょんは、駒の交換値を計算する際に現在はピンを考慮していないため、とんでもない評価になることがある。
将来は、ピンやタイを考慮する必要がある…と思うと結構憂鬱だったりする(--;
序盤は現在のコンピュータ将棋に取って、最大の課題であるといえる。
序盤で差が付くと取り返し難いし、序盤の「差」はなかなか認識し辛い=評価関数が作りがたいのだ。
で、もちろん丸暗記の得意なコンピュータであるから、定跡に頼るわけであるが、定跡のインプリメントの方法は複数存在する。
そのうちの代表的(と思われる)インプリメントは、二つ考えられる。 それぞれ、
前者を単純にインプリメントした時の問題点は、相手が違う手順で組み上げる時に、対応したデータがないために、正しく応接できないことがあることである。
一方、後者を単純にインプリメントすると、間違った手順で組み上げようとして、隙を付かれる可能性がある。
鈴木将棋の定跡は、前者に属するもので、現在、プロ棋士の対局データ12000件程度と、対四間飛車、四間飛車定跡、さらに対東大将棋専用、対柿木将棋専用定跡など、追加定跡それぞれ600手程度を記憶しておき、一致する局面があれば、その局面でのプロの指し手か定跡を選択する。
「コンピュータ将棋の進歩」によれば、柿木将棋の定跡データも、手法としてはこちらに属するものであるとのことであるが、相手の間違いに対して咎める手も定跡に入っており、相手が定跡通りに応接しなくても、単純に正しく応接できなくなるようなことはない。
また、YSSの定跡は後者に属するものだが、手順間違いを起こさないよう、色々とプログラム上で評価値を細かく調整しているとのことである。
うさぴょんの定跡は、前者と後者のハイブリッドを目指したかった(定跡データと一致する間は前者の手法で指し、一致しなくなったら、その局面の直前まで一致していたプロ棋士のデータをもとに、駒の位置による得点表をプログラム内部で作成し、後者の手法で指し続ける、という方法を考えていた)のだが、結局もっと手抜きな実装になっている。
大会版うさぴょんでは、定跡から外れた後、その局面と部分(自陣のみ9x5、右半分の5x9、左半分の5x9、自陣の左半分の5x5、右半分の5x5)が一致する局面で指された手を定跡候補手とし、その手を一手目に指した場合に、ボーナス得点(最大で歩の価値の1.4倍)を与えて、単純に先読みするものとした。これによって、相手が特定の形に組み上げようとしている場合に、それに対する攻撃の形をきちんと組み上げたり、自分が組み上げるべき形に継続して組み上げる効果が得られた。
しかし、これだけでは色々と不十分である。問題点をいくつか挙げる。
このような問題点は、おそらく、
実は、大会直前版うさぴょんでは、相手の飛車角の位置を見ていた。その版では、居飛車に対して舟囲いを採用することはなかった。
しかし、この版には謎のバグ(今では解決しているのだが…)があり、時々定跡ルーチンから戻って来た後、先読みから戻って来る最善手やその応手手順、そしてその評価値がでたらめな値(と言っても、着手可能な手、手順)を返してくることがあった。そのため、安定して動作することを優先し、大会には相手の飛車角の位置に無頓着に指す版で参加した。
余談ではあるが、バグの方は、分かって見れば原因は単純で、飛車交換や角交換を行った場合や、飛車角の位置が一致する棋譜のない場合に、ポインタが異常な領域を指し、その地点の情報を破壊し、先読みの最中に破壊された地点を参照すると、評価がでたらめになるというものであった。
さて、しかし、このような簡易な実装であっても相手がある程度丁寧な手順で応じてくれた続きからならば、十分な威力を発揮する。
TACOS戦では、うさぴょんが完全一致の定跡を外れた後に、部分一致の定跡で進めて、右四間飛車に組み上げ、快勝した。
一方、竜の卵戦 や将皇戦では、速い段階から定跡をはずされ、居飛車相手に舟囲いに組み上げ、ボロ負けした。
これは、前述した通り、解決可能な問題であるので、来年の大会…と言わず、会津で桜が咲くころまでには解決するつもりである。