Bonanzaの3手詰み判定関数はどういう処理になっているのか【後編】

前回(→ http://d.hatena.ne.jp/LS3600/20100104 )の続き。


■ gen_next_evasion_mate


gen_next_evasion_mateは、coroutineになっています。(→ 将棋プログラムに何故coroutineが必要なのか http://d.hatena.ne.jp/LS3600/20091120 ) これで使われているenumは次のようになっています。

// gen_next_evasion_mate(coroutine)で使うphaseを表わすenum
// 詰み回避の検査のためのphase。
mate_king_cap_checker = 0, // まず王手している駒を王で取る手を生成
mate_cap_checker_gen, // 王手している駒を移動して捕獲する手の生成
mate_cap_checker, // ↑で生成した駒をひとつずつ渡す
mate_king_cap_gen, // 王を移動して逃げる手の生成。駒の捕獲あり。ただし王手している駒を捕獲する手は除外。
mate_king_cap, // ↑で生成した駒をひとつずつ渡す
mate_king_move_gen, // 王を移動して逃げる手の生成。駒の捕獲なし。
mate_king_move, // ↑で生成した駒をひとつずつ渡す
mate_intercept_move_gen, // 合駒して受ける手の生成の生成
mate_intercept_move, // ↑で生成した駒をひとつずつ渡す
mate_intercept_weak_move, // ↑↑で生成した駒をひとつずつ渡す。intercept_weak_moveとは利きのない場所への中合い。

3手詰み判定関数の概要は以下の記事を通して読めば理解が深まるでしょう。


http://d.hatena.ne.jp/LS3600/20100101 新春お年玉プレゼント 詰め将棋問題
http://d.hatena.ne.jp/LS3600/20100105 中合い問題の解説 その1
http://d.hatena.ne.jp/LS3600/20100106 中合い問題の解説 その2
http://d.hatena.ne.jp/LS3600/20100107 中合い問題の解説 その3
http://d.hatena.ne.jp/LS3600/20100108 中合い問題の解説 その4
http://d.hatena.ne.jp/LS3600/20100109 中合い問題の解説 その5
http://d.hatena.ne.jp/LS3600/20100110 中合い問題の解説 その6



あと、Bonanza 4.1.2のほうのmate3.cに含まれるバグについては保木さんから、次のメールをいただきました。

王手回避の駒打ちは,「飛・香・歩」の順番で,可能なものを1つだけ選択し
ます.しかし中合の場合は,どうせ取られるので「歩・香・飛」の順番で1つ
選択すべきです.


1) 利きのない場所に合い駒(中合い)した場合はすぐに取り返される変化を調べるので、攻め方に渡すならば、「歩」と「飛」を持っているならば、「歩」を渡して詰まなければ「飛」を渡しても詰まない。


2) 逆に利きのある場所に合い駒する場合は、その駒を取らずに1手で詰むか調べるので、受け方は、「飛」を合い駒して、自玉に利かせて、それで1手で詰むなら「歩」を合い駒しても詰む。


という理屈のようです。これは私は気づきませんでした。


もうひとつ、保木さん情報。

あと,mate_weak_or() 内で

direc = (int)adirec[SQ_WKING][from];
if ( direc
&& is_pinned_on_white_king( ptree, from, direc ) ) { return 0; }

として攻め方が pin されている駒を動かさないようにしているのですが,下の
ように飛び駒と王がそれぞれ向かい合っている場合は同飛と王手してくれま
せん.






direc = (int)adirec[SQ_WKING][from];
if ( direc
&& direc != (int)adirec[SQ_BKING][from]
&& is_pinned_on_white_king( ptree, from, direc ) ) { return 0; }

とすべきでした.あと,この後にある InCheck() のテストは不要なようです.

はい、そうですね。私はpin checkつきのmake_moveを使うようにソースを書き換えたので(→ http://d.hatena.ne.jp/LS3600/20091229 )、それは保木さんにお伝えするのを忘れておりました。ちなみに上の処理はIsDiscoverWK/BKを使うと良いように思います。(保木さんは作ったまま忘れておられる?)


■ まとめ


これで3手詰め判定関数についての説明はすべて終わりました。