Blunderのソース読み
____ / \ ( ;;;;( / _ノ ヽ__\) ;;;;) / (─) (─ /;;/ | (__人__) l;;,´ あらゆる技術が全部投入されてて驚いたお / ∩ ノ)━・'/ ( \ / _ノ´.| | .\ " /__| | \ /___ /
AlphaBeta.csとTranspositonTable.csはけっこう読みました。
よく解らなかった所や感心したところをメモ
- sigular判定をしている。
これは昔YSSの掲示板で目にして、DeepBlueもやっているってことで
実装したかったんですが、いざやろうと思うと難しいので、助かります。参考にさせてもらいます。
(読みが深い理由?)
// singularかどうか判定 if (GameTreeConfig.TestRootSingular && isRoot && NextResult.Singular && MinEval + GameTreeConfig.SingularMarginS < NextResult.Max) { int bound = NextResult.Max - GameTreeConfig.SingularMarginS;
- NullMovePruningで、パスしたら詰みだったら詰めろかかってるので
// 詰んでたら必死状態 if (value <= MinEval) { depth += GameTreeConfig.ThreatExtDepth; state |= NodeState.MateThreat; }
↑必死じゃなくて詰めろと思う
詰めろ状態にして探索延長(詰めろ状態だとLMRを抑制)
NMPは非PVノードでやるもんだと思いますが、延長したら読みが浅くならないのかなあ? でも最後の寄せ合いでは強いのかも。
確かCraftyは同じように詰めろ延長をしていて、YSSの山下さんがブログで詰めろ延長をしても強くならなかったと書かれていた記憶があります
- 通常探索内でwindowが広かったらaspirationSearch。えー!
// window幅がいっぱいあったらaspiration。 return AspirationSearch(context, alpha, beta, forecastEval, newDepth
これは見たことがない。aspirationって反復進化とセットでやるもんと思ってた。
多重反復進化のノリで、多重AspirationSearchって感じ?
段々深くする方向と、段々広げる方向があるってことか? これって囲碁のProgressiveWidningと近いのかも?(よく解らんけど)
目から鱗だった。効果はわからんけど
- ReCapture延長
} else if ((state & NodeState.CanReCapExt) != 0 && // フラグちゃんと立ってる時だけ。 i <= 3 && // オーダリングそこそこ上位のみ。(手抜き) IsReCapture(context, move, out recaptureType)) { // recaptureで延長 if (recaptureType == 0) { context.Local.ExtensionCounts[2]++; newDepth += GameTreeConfig.ReCaptureExtDepth1; } else { context.Local.ExtensionCounts[3]++; newDepth += GameTreeConfig.ReCaptureExtDepth2; } // 子ノードでは延長しない newState &= ~NodeState.CanReCapExt;
同じ駒同士で取り合ってたら、浅く延長ってあたりは、「Bona4を見て参考にしている」というのが解ります
しかし、i<=3って、オーダリング的にi<=3以内しかReCap延長しないってこと?
終盤は、オーダリングが後半のReCapを延長した方がいい場合が出てくると思う。さすがにi<=3はないんじゃないだろうか?
子ノード延長をしてない。しない方がいいのかなあ。
今はNullMovePruning以外は常にやってるんですが、やらないほうが反復進化が回るのは確かと思う。
- hash型ProbCut
これって私が書いてたアイデアが元ネタ?
http://d.hatena.ne.jp/mkomiya/20080426/1209166463
少なくとも他では見たことがないので。
効果は微妙な気もしますけど、探索木の上の方で枝狩り出来ると大きいと思うので
// Hash型ProbCut int remainDiff = depth - trans.Depth; if (remainDiff <= DepthUnit * 1) { if (trans.Upper + GameTreeConfig.HashProbCutMargin1 <= alpha) { context.Local.HPCSuccess[0]++; SetLeafTransMove(context, trans.BestMove); return alpha; } else if (beta <= trans.Lower - GameTreeConfig.HashProbCutMargin1) {