@@ -97,17 +97,17 @@ func (e *ebfStruct) add(nodes uint64) {
9797func (e * ebfStruct ) clear () {
9898 * e = (* e )[:0 ]
9999}
100- func (e * ebfStruct ) ebf () float64 {
100+ func (e * ebfStruct ) ebf (depth int ) float64 {
101101 if len (* e ) < 4 {
102102 return 0
103103 }
104104 ebf := 0.0
105- prevNodes1 := float64 ((* e )[len (* e )- 2 ])
106- prevNodes2 := float64 ((* e )[len (* e )- 3 ])
107- prevNodes3 := float64 ((* e )[len (* e )- 4 ])
105+ nodes := float64 ((* e )[len (* e )- 1 ]) // the last depth
106+ prevNodes := float64 ((* e )[len (* e )- 2 ])
108107
109- if prevNodes2 > 0.0 && prevNodes3 > 0.0 {
110- ebf = (prevNodes2 / prevNodes3 + prevNodes1 / prevNodes2 ) / 2
108+ if nodes > 0.0 && prevNodes > 0.0 {
109+ // ebf = (prevNodes2/prevNodes3 + prevNodes1/prevNodes2) / 2
110+ ebf = nodes / prevNodes
111111 }
112112 fmt .Printf ("ebf: %0.2f age=%v Used=%v Stored: %v Tried: %v Found: %v Prunes: %v Best: %v\n " , ebf , trans .age , trans .cntUsed , trans .cStores , trans .cTried , trans .cFound , trans .cPrune , trans .cBest )
113113 return ebf
@@ -144,32 +144,38 @@ func root(toEngine chan bool, frEngine chan string) {
144144 trans .initSearch () // incr age coounters=0
145145
146146 genAndSort (0 , b , & ml )
147- bm := ml [0 ]
148- bs := noScore
149147 depth = 0
150148
151149 transDepth := 0
152-
150+ inCheck := b .isAttacked (b .King [b .stm ], b .stm .opp ())
151+ bm := ml [0 ]
152+ bs := noScore // bm keeps the best from prev iteration in case of immediate stop before first is done in this iteration
153153 for depth = 1 ; depth <= limits .depth && ! limits .stop ; depth ++ {
154154 ml .sort ()
155155 bs = noScore // bm keeps the best from prev iteration in case of immediate stop before first is done in this iterastion
156156 alpha , beta = minEval , maxEval
157- for ix , mv := range ml {
157+ for ix , mv := range ml { // root move loop
158158 childPV .clear ()
159+
159160 b .move (mv )
160- tell ("info depth " , strconv .Itoa (depth ), " currmove " , mv .String (), " currmovenumber " , strconv .Itoa (ix + 1 ))
161- //fmt.Printf("alpha=%v beta=%v\n",alpha,beta)
162- score := - search (- beta , - alpha , depth - 1 , 1 , & childPV , b )
161+ tell (fmt .Sprintf ("info depth %v currmove %v currmovenumber %v" , depth , mv .String (), ix + 1 ))
162+ lmrRed := 0
163+ ext := 0 // TODO: make extension function
164+ if ext == 0 {
165+ lmrRed = lmr (mv , inCheck , depth , ix + 1 , ix , b )
166+ }
167+ score := noScore
168+ if ix == 0 {
169+ score = - search (- beta , - alpha , depth - 1 + ext , 1 , & childPV , b ) // full search
170+ } else {
171+ score = - search (- alpha - 1 , - alpha , depth - 1 + ext - lmrRed , 1 , & childPV , b )
172+ if score > alpha && ! limits .stop { // re-search due to PVS and/or lmr
173+ score = - search (- beta , - alpha , depth - 1 + ext , 1 , & childPV , b )
174+ }
175+ }
163176
164177 b .unmove (mv )
165178
166- ////////////////////////////////////
167- if ! checkKey (b ) {
168- fmt .Println ("fullkey=" , b .fullKey (), "Key" , b .key , mv .StringFull ())
169- fmt .Println ("INVALID KEY AFTER UNMOVE ROOT" )
170- }
171- ///////////////////////////////////////
172-
173179 if limits .stop {
174180 break
175181 }
@@ -189,9 +195,11 @@ func root(toEngine chan bool, frEngine chan string) {
189195 tell (fmt .Sprintf ("info score cp %v depth %v nodes %v time %v pv " , bm .eval (), depth , cntNodes , int (t1 .Seconds ()* 1000 )), pv .String ())
190196 }
191197 }
198+ if ! limits .stop {
199+ ebfTab .add (cntNodes )
200+ }
192201
193- ebfTab .add (cntNodes )
194- }
202+ } // end ID
195203 ml .sort ()
196204
197205 trans .store (b .fullKey (), bm , transDepth , 0 , bs , scoreType (bs , alpha , beta ))
@@ -202,16 +210,16 @@ func root(toEngine chan bool, frEngine chan string) {
202210 if t1 .Seconds () != 0 {
203211 nps = float64 (cntNodes ) / t1 .Seconds ()
204212 }
205- ebfTab .ebf ()
206- tell (fmt .Sprintf ("info score cp %v depth %v nodes %v time %v nps %v pv %v" , bm .eval (), depth - 1 , cntNodes , int (t1 .Seconds ()* 1000 ), uint (nps ), pv .String ()))
213+ ebfTab .ebf (transDepth )
214+ tell (fmt .Sprintf ("info score cp %v depth %v nodes %v time %v nps %v pv %v" , bm .eval (), transDepth , cntNodes , int (t1 .Seconds ()* 1000 ), uint (nps ), pv .String ()))
207215 frEngine <- fmt .Sprintf ("bestmove %v%v" , sq2Fen [bm .fr ()], sq2Fen [bm .to ()])
208216 }
209217}
210218
211219//TODO search: Late Move Reduction
212220
213221//TODO search: Internal Iterative Depening
214- //TODO search: Delta Pruning
222+ //TODO search: Futility/ Delta Pruning
215223//TODO search: more complicated time handling schemes
216224//TODO search: other reductions and extensions
217225func search (alpha , beta , depth , ply int , pv * pvList , b * boardStruct ) int {
@@ -274,7 +282,7 @@ func search(alpha, beta, depth, ply int, pv *pvList, b *boardStruct) int {
274282 if depth <= 3 { // static
275283 // if you don't beat me with 100 points,
276284 // then I think your position sucks
277- sc = - qs (- beta + 1 , b )
285+ sc = - qs (- beta + 1 , b ) // TODO: maybe 75-100 points bonus for opponent?
278286 } else { // dynamic
279287 sc = - search (- beta , - beta + 1 , depth - 3 - 1 , ply , & childPV , b )
280288 }
@@ -294,7 +302,7 @@ func search(alpha, beta, depth, ply int, pv *pvList, b *boardStruct) int {
294302 bm := noMove
295303
296304 var genInfo = genInfoStruct {sv : 0 , ply : ply , transMove : transMove }
297- cntMoves := 0
305+ cntMoves := 0
298306 next = nextNormal
299307 for mv , msg := next (& genInfo , b ); mv != noMove ; mv , msg = next (& genInfo , b ) {
300308 _ = msg
@@ -304,17 +312,22 @@ func search(alpha, beta, depth, ply int, pv *pvList, b *boardStruct) int {
304312 }
305313
306314 childPV .clear ()
307-
308- if pvNode && bm != noMove {
309- score = - search (- alpha - 1 , - alpha , depth - 1 , ply + 1 , & childPV , b )
315+ lmrRed := 0
316+ ext := 0 // TODO: make extension function
317+ if ext == 0 {
318+ lmrRed = lmr (mv , inCheck , depth , genInfo .sv , cntMoves , b )
319+ }
320+ if pvNode && cntMoves == 0 {
321+ score = - search (- beta , - alpha , depth - 1 + ext , ply + 1 , & childPV , b )
322+ } else {
323+ score = - search (- alpha - 1 , - alpha , depth - 1 + ext - lmrRed , ply + 1 , & childPV , b )
310324 if score > alpha {
311- score = - search (- beta , - alpha , depth - 1 , ply + 1 , & childPV , b )
325+ score = - search (- beta , - alpha , depth - 1 + ext , ply + 1 , & childPV , b )
312326 }
313- } else {
314- score = - search (- beta , - alpha , depth - 1 , ply + 1 , & childPV , b )
315327 }
316- cntMoves ++
328+
317329 b .unmove (mv )
330+ cntMoves ++
318331
319332 if score > bs {
320333 bs = score
@@ -362,10 +375,10 @@ func search(alpha, beta, depth, ply int, pv *pvList, b *boardStruct) int {
362375 }
363376 }
364377
365- if cntMoves == 0 { // whe didn't find any legal moves - either mate or stalemate
366- sc := 0 // we could have a contempt value here instead
367- if inCheck { // must be a mate
368- sc = - mateEval + ply + 1
378+ if cntMoves == 0 { // we didn't find any legal moves - either mate or stalemate
379+ sc := 0 // we could have a contempt value here instead
380+ if inCheck { // must be a mate
381+ sc = - mateEval + ply + 1
369382 }
370383
371384 if useTT {
@@ -380,6 +393,22 @@ func search(alpha, beta, depth, ply int, pv *pvList, b *boardStruct) int {
380393 return bs
381394}
382395
396+ // compute late move reduction
397+ func lmr (mv move , inCheck bool , depth , sv , cntMoves int , b * boardStruct ) int {
398+ interesting := inCheck || mv .cp () != empty || mv .pr () != empty ||
399+ b .isAttacked (b .King [b .stm ], b .stm .opp ()) ||
400+ (b .stm == WHITE && mv .pc () == wP && mv .to () >= A6 ) ||
401+ (b .stm == BLACK && mv .pc () == bP && mv .to () <= H3 ) // even big threats? castling?
402+ red := 0
403+ if ! interesting && depth >= 3 && sv >= nextFirstNonCp {
404+ red = 1
405+ if depth >= 5 && sv >= nextFirstNonCp {
406+ red = depth / 3
407+ }
408+ }
409+ return red
410+ }
411+
383412// is this a position to avoid null move?
384413func (b * boardStruct ) isAntiNullMove () bool {
385414 if b .wbBB [b .stm ] == b .pieceBB [King ]& b .wbBB [b .stm ] {
@@ -879,7 +908,7 @@ func nextNormal(genInfo *genInfoStruct, b *boardStruct) (move, string) {
879908 for ix := 0 ; ix < len (* ml ); ix ++ {
880909 if (* ml )[ix ].cmpFrToP (genInfo .transMove ) || (* ml )[ix ].cmpFrToP (genInfo .counterMv ) ||
881910 (* ml )[ix ].cmpFrToP (killers [genInfo .ply ].k1 ) || (* ml )[ix ].cmpFrToP (killers [genInfo .ply ].k2 ) {
882- continue
911+ continue
883912 }
884913 sc := int (history .get ((* ml )[ix ].fr (), (* ml )[ix ].to (), b .stm ))
885914 if sc > bs {
@@ -939,13 +968,13 @@ func startPerft(depth int, bd *boardStruct) uint64 {
939968 continue
940969 }
941970 dbg := false
942- /*
943- /////////////////////////////////////////////////////////////
944- if mv.fr() == D4 && mv.to() == F4 {
945- dbg = true
946- }
947- /////////////////////////////////////////////////////////////
948- */
971+ /*
972+ /////////////////////////////////////////////////////////////
973+ if mv.fr() == D4 && mv.to() == F4 {
974+ dbg = true
975+ }
976+ /////////////////////////////////////////////////////////////
977+ */
949978 count := perft (dbg , depth - 1 , 1 , bd )
950979 totCount += count
951980 fmt .Printf ("%2d: %v \t %v \t %v\n " , ix + 1 , mv .String (), count , msg )
@@ -976,29 +1005,29 @@ func perft(dbg bool, depth, ply int, bd *boardStruct) uint64 {
9761005 }
9771006 _ = msg
9781007 deb := false
979- /*
980- ////////////////////////////////////////////////////////////////
981- if dbg && mv.fr() == F5 && mv.to() == F4 {
982- deb = true
983- }
984- if dbg && mv.fr() == E2 && mv.to() == E4 {
985- deb = true
986- }
987- ////////////////////////////////////////////////////////////////
988- */
1008+ /*
1009+ ////////////////////////////////////////////////////////////////
1010+ if dbg && mv.fr() == F5 && mv.to() == F4 {
1011+ deb = true
1012+ }
1013+ if dbg && mv.fr() == E2 && mv.to() == E4 {
1014+ deb = true
1015+ }
1016+ ////////////////////////////////////////////////////////////////
1017+ */
9891018 cnt := perft (deb , depth - 1 , ply + 1 , bd )
9901019 count += cnt
991- /*
992- /////////////////////////////////////////////
993- if dbg && !deb {
994- fmt.Println(ix+1, ":(e4) ", mv.String(), msg, "\t", cnt)
995- if ix==1{
996- fmt.Println("K1",killers[ply].k1.StringFull())
997- fmt.Println("K2",killers[ply].k2.StringFull())
1020+ /*
1021+ /////////////////////////////////////////////
1022+ if dbg && !deb {
1023+ fmt.Println(ix+1, ":(e4) ", mv.String(), msg, "\t", cnt)
1024+ if ix==1{
1025+ fmt.Println("K1",killers[ply].k1.StringFull())
1026+ fmt.Println("K2",killers[ply].k2.StringFull())
1027+ }
9981028 }
999- }
1000- ////////////////////////////////////////////
1001- */
1029+ ////////////////////////////////////////////
1030+ */
10021031 bd .unmove (mv )
10031032 ix ++
10041033 }
0 commit comments