daruma3940の日記

理解や文章に間違い等あればどんなことでもご指摘お願いします

差し手生成部なのじぇ

f:id:daruma3940:20160520223745p:plain
ふうぅ~とりあえずやねうら王とAperyの差し手生成部を読んだのじぇ

f:id:daruma3940:20160521003616p:plain
お疲れさまね…..

f:id:daruma3940:20160520223745p:plain
ざっくりとした概略を文字で書くならこんな感じなのじぇ

やねうら王について

movepickerのmoves[600]が差し手配列

差し手生成関数は探索関数中のMovePicker mp(pos,ttMove);から呼び出される。



MovePicker(const Position& pos_,Move ttMove) の中で呼び出される
template<MOVE_GEN_TYPE GenType>
ExtMove* generateMoves(const Position& pos, ExtMove* mlist)

先手後手で呼び出す関数を分けるもの
template<MOVE_GEN_TYPE GenType, bool All>
ExtMove* generateMoves(const Position& pos, ExtMove* mlist,Square sq = SQ_NB)

指し手のタイプ別に分けるものの3種類あり
template<MOVE_GEN_TYPE GenType,Color Us,bool All>
ExtMove* generate_general(const Position& pos, ExtMove* mlist,Square recapSq=SQ_NB)

指し手の駒種別に差し手を生成するのは

~駒移動
struct GeneratePieceMovesでありこれには5しゅるいあり、
角飛車の移動                    からの make_move_target
成れない手による移動          からの make_move_target
成れない手(王を除く)           からのMAKE_MOVE_TARGET(target2);
歩の移動                    からのmake_move   or  make_move_promote
桂馬香車銀の移動              からの make_move_target
ここで差し手は生成される。

~駒うち
struct GenerateDropMovesの内部の
(歩)FOREACH_BB(target2, sq, { mlist++->move = make_move_drop(PAWN,sq); });
(どこでも打てる)make_move_drop 
(香車桂馬)FOREACH_BB(target2, sq, { UNROLLER1({ mlist++->move = (Move)(drops[i] + sq); }); }); 

Apery twgについて

movepickerのMoveStack leagalmoves_[594]が差し手配列

探索関数の中のnextmove()でgonextphaseが呼ばれ

goNextPhaseでフェーズにより分けられながら差し手が生成されている(!タイプ別差し手遅延生成!)
その中で
template <MoveType MT>
MoveStack* generateMoves(MoveStack* moveStackList, const Position& pos)というのが呼ばれている (駒うちはgenerateMoves<Drop>(currMove(), pos());)
その中でさらに色別で分けられ(template <MoveType MT, Color US, bool ALL = false>struct GenerateMoves )
その中で全駒種別に用意された(template <MoveType MT, PieceType PT, Color US, bool ALL> struct GeneratePieceMoves)の中の


成り makePromoteMove<MT>(Pawn, from, to, pos);
成らず makeNonPromoteMove<MT>(Pawn, from, to, pos);

この関数の中の
template <MoveType MT, PromoteMode PM>
inline Move selectedMakeMove(const PieceType pt, const Square from, const Square to, const Position& pos) 
この関数内でようやく
movetype別差し手生成が行われる


駒打ち
generateMoves<Drop>(currMove(), pos())からの

(色分け)
template <MoveType MT>
MoveStack* generateMoves(MoveStack* moveStackList, const Position& pos) からの
(種類分け(drop固定))
template <Color US> struct GenerateMoves<Drop, US> 
(駒打ち)
template <Color US>
MoveStack* generateDropMoves(MoveStack* moveStackList, const Position& pos, const Bitboard& target)からの
makeDropMove

f:id:daruma3940:20160521003616p:plain
やたらと複雑ね…

f:id:daruma3940:20160520223745p:plain
図にするとこうなるのじぇ

やねうら王
f:id:daruma3940:20160530233921j:plain
f:id:daruma3940:20160530233938j:plain

Apery
f:id:daruma3940:20160530233952j:plain
f:id:daruma3940:20160530234108j:plain
f:id:daruma3940:20160530234113j:plain

f:id:daruma3940:20160520223745p:plain
同じような名前の関数templateとそれに包まれた同じような関数templateが多すぎるのじぇ!
分かりにくいと思うけど我慢するのじぇ
多分この呼び出し構造だけでもわかれば読んでいくのも楽になるはずなのじぇ
間違ってるところがあれば指摘してほしいのじぇ

f:id:daruma3940:20160520223530p:plain
ちょっと複雑すぎるよ!なんでこんな似たような名前のtemplate関数ばっかりなの!?

f:id:daruma3940:20160520223745p:plain
似たような名前でわかりにくいのはまりちゃも同意なのじぇ。
これにはどういった最適化に関する意味があるのかはまりちゃには分からないのじぇ。コードが読みにくくなるだけだと思うのじぇ。
でもあのやねうら王もAperyもわざわざこんなことをするということは何か意味があると思っているのじぇ。

でもtemplateをたくさん使っているのはなぜだか分るのじぇ
多分過コーディングを防ぐためであると思うのじぇ

f:id:daruma3940:20160520223530p:plain
過コーディング??

f:id:daruma3940:20160520223745p:plain
なんかよくわからないけどあんまりコードが長くなりすぎると棋力が下がってしまうらしいのじぇ。
(平岡さんの2016年3月2日のツイート参照)

f:id:daruma3940:20160521003616p:plain それとtemplateってどう関係があるのかしら?

f:id:daruma3940:20160520223745p:plain
ちょっとまりちゃもあんまりよくわかってないけど
やねうら王さんのコンピューター将棋ブログの
Stockfish完全解析のsearch 探索部の記事の
search.cppのtemplate Value search()のところを読んでもらえば分かると思うのじぇ

(勝手にリンクを張るのは怖いのじぇ)

多分ここの部分もそういう原理だと思うのじぇ

template<MOVE_GEN_TYPE GenType,Color Us,bool All>
ExtMove* generate_general()
にconst Bitboard targetってのがあるし…

ごめんなさいこの記事プログラミングあんまりよくわかってないときに書いた記事だから信用しないでください(;´・ω・)

templateについてはmerom686さんに昔聞いてみたことがあるのでここを読んでください(´・ω・`) ask.fm 条件分岐を減らせたり、データを読みとる必要がなくなったりして高速化できることがtemplateを使っている理由だと今では思っています

平岡さんの言っていた過コーディングについてはいまだに何のことなのかわかってないです(´・ω・`) 過コーディングはtemplateとは関係がないような気がしますね