I think Blueberry would win it on plydepth, as it only needs 4 plies. Unfortunately because of the horizon extensions which, as the name implies, are designed to look over the event horizon at plydepth = 0 where the quiescence search starts, this still takes 2 minutes and 12 seconds. Basically the idea with horizon extensions was to extend multiple 1 ply searches so it behaves a little like a Monte Carlo search, but because q-search and IID searches are now also invoked with up to seven plies deep searches when the eval is going up,
AND, if the search from best_move is going down instead of up, I also extend every nextbest_move, the idea is a bit lost. This really becomes too costly even in a 4 ply deep search, a one ply search is something very different from a 7 ply search after all.
When I bypass all horizon extensions I get a better result:
[D]rn1r2k1/1bqpbppp/pp2pn2/6N1/2P5/1PN1P3/PBQ1BPPP/3R1RK1 w - -
Engine: Blueberry Beta 4 DM70 Build
370 (256 MB)
by F. Letouzey, T. Gaksch, E. de Groot
2/14 0:00 +0.41 1.Nce4 Nxe4 2.Nxe4 f5 (3.033)
2/26 0:00 +0.43 1.Na4 h6 2.Bxf6 Bxf6 3.Qh7+ Kf8
4.Nh3 g6 5.Qxh6+ Kg8 (117.220)
2/26 0:00 +0.42 1.Na4 h6 2.Nh3 Nc6 3.Nc5 bxc5 (140.067)
2/29 0:00 +0.67 1.Na4 h6 2.Bxf6 Bxf6 3.Qh7+ Kf8
4.Ne4 Bxe4 5.Qxe4 Nc6 6.Qh7 Ne7
7.Qh8+ Ng8 (290.331)
3/29 0:00 +1.17 1.Na4 e5 2.f4 Nc6 3.Bd3 (422.787)
4/35 0:01 +0.44 1.Na4 h6 2.Bxf6 Bxf6 3.Qh7+ Kf8
4.Ne4 Bxe4 5.Qxe4 (699.036) 543
4/42 0:05 +1.24 1.Nd5 exd5 2.Bxf6 Bxf6 3.Qxh7+ Kf8
4.cxd5 Be5 5.Rc1 Bxh2+ 6.Qxh2 Qxh2+
7.Kxh2 f6 8.Nh7+ Kg8 9.Rc7 Bxd5 (3.204.965) 598
4/48 0:10 +1.24 1.Nd5 exd5 2.Rc1 dxc4 3.bxc4 Bxg2
4.Kxg2 Kf8 5.Bxf6 gxf6 6.Nxh7+ Ke8 (6.834.442) 627
4/51 0:17 +1.23 1.Nd5 exd5 2.Bxf6 Bxf6 3.Qxh7+ Kf8
4.cxd5 d6 5.Qh8+ Ke7 6.Rc1 Rxh8
7.Rxc7+ Nd7 8.Nxf7 Bxd5 9.Nxh8 Rxh8 (10.905.957) 632
5/51 0:17 +1.85 1.Nd5 exd5 2.Bxf6 Bxf6 3.Qxh7+ Kf8
4.cxd5 d6 5.Qh8+ Ke7 6.Qh5 g6 (10.989.516) 632
6/51 0:19 +0.62 1.Nd5 exd5 2.Bxf6 Bxf6 3.Qxh7+ Kf8
4.cxd5 d6 5.Qh8+ Ke7 6.Qh5 g6 7.Qh4 Bxg5
8.Qxg5+ Kf8 (12.298.280) 628
7/51 0:36 +0.62 1.Nd5 exd5 2.Bxf6 Bxf6 3.Qxh7+ Kf8
4.cxd5 d6 5.Qh8+ Ke7 6.Qh5 g6 7.Qh4 Bxg5
8.Qxg5+ Kf8 (21.888.663) 599
8/51 1:19 +1.00 1.Nd5 exd5 2.Bxf6 Bxf6 3.Qxh7+ Kf8
4.cxd5 d6 5.Ne4 Nd7 6.Bg4 Re8 7.Bxd7 Rxe4
8.Qh8+ Ke7 (46.002.875) 577
9/51 2:09 +2.55 1.Nd5 exd5 2.Bxf6 Bxf6 3.Qxh7+ Kf8
4.cxd5 d6 5.Bh5 Nd7 6.Bxf7 Qb8 7.Be6 Ke7
8.Ne4 Rh8 9.Qf5 Nc5 (74.161.322) 572
10/51 2:12 +2.55 1.Nd5 exd5 2.Bxf6 Bxf6 3.Qxh7+ Kf8
4.cxd5 d6 5.Bh5 Nd7 6.Bxf7 Qb8 7.Be6 Ke7
8.Ne4 Rh8 9.Qf5 Nc5 (75.794.669) 572
11/64 27:42 +2.25 1.Nd5 exd5 2.Bxf6 Bxf6 3.Qxh7+ Kf8
4.cxd5 d6 5.Bh5 Bxg5 6.Qh8+ Ke7
7.Qxg7 (964.933.454) 580
12/64 28:46 +2.25 1.Nd5 exd5 2.Bxf6 Bxf6 3.Qxh7+ Kf8
4.cxd5 d6 5.Bh5 Bxg5 6.Qh8+ Ke7
7.Qxg7 (1.001.303.638) 580
13/64 29:50 +2.28 1.Nd5 exd5 2.Bxf6 Bxf6 3.Qxh7+ Kf8
4.cxd5 d6 5.Bh5 Bxg5 6.Qxg7+ Kxg7
7.Rc1 Bxd5 8.Kh1 Bxg2+ 9.Kxg2 Bxe3
10.Rxc7 Bxf2 11.Rxf2 Nd7 12.Bg4 Nc5
13.b4 Kg6 14.Bf5+ (1.038.092.467) 579
14/64 30:11 +2.28 1.Nd5 exd5 2.Bxf6 Bxf6 3.Qxh7+ Kf8
4.cxd5 d6 5.Bh5 Bxg5 6.Qxg7+ Kxg7
7.Rc1 Bxd5 8.Kh1 Bxg2+ 9.Kxg2 Bxe3
10.Rxc7 Bxf2 11.Rxf2 Nd7 12.Bg4 Nc5
13.b4 Kg6 14.Bf5+ (1.049.554.950) 579
15/64 37:43 +2.52 1.Nd5 exd5 2.Bxf6 Bxf6 3.Qxh7+ Kf8
4.cxd5 d6 5.Bh5 Bxg5 6.Qh8+ Ke7
7.Qxg7 (1.300.711.160) 574
16/79 68:05 +2.44 1.Nd5 exd5 2.Bxf6 Bxf6 3.Qxh7+ Kf8
4.cxd5 d6 5.Bh5 Bxg5 6.Qh8+ Ke7
7.Qxg7 Rf8 8.Qxg5+ Ke8 9.Rc1 Qd8
10.Qf5 Qe7 11.Rce1 (2.239.209.553) 548
17/79 84:39 +2.51 1.Nd5 exd5 2.Bxf6 Bxf6 3.Qxh7+ Kf8
4.cxd5 d6 5.Bh5 Bxg5 6.Qh8+ Ke7
7.Qxg7 Rf8 8.Qxg5+ Ke8 9.Rc1 Qd8
10.Qf5 Qe7 11.Bf3 Qd7 12.Qe4+ Qe7
13.Qxe7+ Kxe7 14.Rc7+ (2.803.164.679) 551
18/80 107:40 +2.77 1.Nd5 exd5 2.Bxf6 Bxf6 3.Qxh7+ Kf8
4.cxd5 d6 5.Bh5 Bxg5 6.Qh8+ Ke7
7.Qxg7 Rf8 8.Qxg5+ Ke8 9.Rd4 Qe7
10.Qf5 Nd7 11.Re4 Ne5 12.Rb4 (3.479.502.463) 538
19/80 116:33 +2.73 1.Nd5 exd5 2.Bxf6 Bxf6 3.Qxh7+ Kf8
4.cxd5 d6 5.Bh5 Bxg5 6.Qh8+ Ke7
7.Qxg7 Rf8 8.Qxg5+ Ke8 9.Rd4 Qe7
10.Qf5 Nd7 11.Re4 Ne5 12.f4 Bxd5
13.fxe5 Bxe4 14.Qxe4 (3.790.635.648) 542
best move: Nc3-d5 time: 122:52.031 min n/s: 543.727 CPU 100.0% n/s(1CPU): 543.727 nodes: 4.008.270.000
Maybe I should not post the code for the horizon extensions because in the present form they are clearly not working and the design is very crude. But who knows it may help to think about better ways of doing something similar and it is of course very easy to scale everything down again so that the impact is just limited and, in a limited form, who knows not such a drain on the search.
Code: Select all
// [EdG: horizon extensions hack]
if (node_type == NodePV && height <= SearchCurrent[ThreadId]->act_iteration + 10) sharpen_PV = true;
else sharpen_PV = false;
if (depth == 1 && best_move != MoveNone && nextbest_value != ValueNone && depth_best_move < depth
&& !Singular_Extended && best_value < beta && best_value >= alpha - 50 && (extended || sharpen_PV) &&
height >= SearchCurrent[ThreadId]->act_iteration + 3 /*&& nextbest_value <= alpha - 100*/) {
move_do(board,best_move,undo);
old_value = best_value;
best_value = -full_search(board,-(alpha + 51),-(alpha + 50),depth_best_move + 1,height+1,new_pv,NodeCut,true,false,ThreadId);
best_value = -full_search(board,-(alpha + 51),-(alpha + 50),depth_best_move + 2,height+1,new_pv,NodeCut,true,false,ThreadId);
if (best_value >= old_value - 50 || sharpen_PV) {
old_value = best_value;
best_value = -full_search(board,-(alpha + 51),-(alpha + 50),depth_best_move + 3,height+1,new_pv,NodeCut,true,false,ThreadId);
if (best_value > old_value - 50) {
best_value = -full_search(board,-(best_value + 1),-(best_value),depth_best_move + 4,height+1,new_pv,NodeCut,true,true,ThreadId);
best_value = -full_search(board,-(best_value + 1),-(best_value),depth_best_move + 5,height+1,new_pv,NodeCut,true,true,ThreadId);
best_value = -full_search(board,-(best_value + 1),-(best_value),depth_best_move + 6,height+1,new_pv,NodeCut,true,true,ThreadId);
old_value = best_value;
best_value = -full_search(board,-(best_value + 1),-(best_value),depth_best_move + 7,height+1,new_pv,NodeCut,true,true,ThreadId);
if (best_value > old_value - 50) {
old_value = best_value;
best_value = -full_search(board,-beta,-alpha,depth_best_move + 5,height+1,new_pv,NodePV,true,false,ThreadId);
if (best_value > old_value && best_value < beta && height < SearchCurrent[ThreadId]->act_iteration + 20){
old_value = best_value;
best_value = -full_search(board,-beta,-alpha,depth_best_move + 6,height+1,new_pv,NodePV,true,false,ThreadId);
if (best_value > old_value && best_value < beta && height < SearchCurrent[ThreadId]->act_iteration + 20)
best_value = -full_search(board,-beta,-alpha,depth_best_move + 7,height+1,new_pv,NodePV,true,false,ThreadId);
}
}
}
}
move_undo(board,best_move,undo);
pv_cat(pv,new_pv,best_move);
ASSERT(value_is_ok(best_value));
if (best_value > alpha) {
alpha = best_value;
}
if (best_value <= nextbest_value) {
move_do(board,nextbest_move,undo);
old_value = nextbest_value;
nextbest_value = -full_search(board,-(alpha + 51),-(alpha + 50),depth_best_move + 1,height+1,new_pv,NodeCut,true,false,ThreadId);
if (nextbest_value >= old_value - 50 || sharpen_PV) {
old_value = nextbest_value;
nextbest_value = -full_search(board,-(alpha + 51),-(alpha + 50),depth_best_move + 2,height+1,new_pv,NodeCut,true,false,ThreadId);
if (nextbest_value > old_value - 50) {
nextbest_value = -full_search(board,-(nextbest_value + 1),-(nextbest_value),depth_best_move + 3,height+1,new_pv,NodeCut,true,true,ThreadId);
nextbest_value = -full_search(board,-(nextbest_value + 1),-(nextbest_value),depth_best_move + 4,height+1,new_pv,NodeCut,true,true,ThreadId);
nextbest_value = -full_search(board,-(nextbest_value + 1),-(nextbest_value),depth_best_move + 5,height+1,new_pv,NodeCut,true,true,ThreadId);
nextbest_value = -full_search(board,-(nextbest_value + 1),-(nextbest_value),depth_best_move + 6,height+1,new_pv,NodeCut,true,true,ThreadId);
old_value = nextbest_value;
nextbest_value = -full_search(board,-beta,-alpha,depth_best_move + 4,height+1,new_pv,NodePV,true,false,ThreadId);
if (nextbest_value > old_value && nextbest_value < beta && height < SearchCurrent[ThreadId]->act_iteration + 25){
old_value = nextbest_value;
nextbest_value = -full_search(board,-beta,-alpha,depth_best_move + 5,height+1,new_pv,NodePV,true,false,ThreadId);
if (nextbest_value > old_value && nextbest_value < beta && height < SearchCurrent[ThreadId]->act_iteration + 25)
nextbest_value = -full_search(board,-beta,-alpha,depth_best_move + 6,height+1,new_pv,NodePV,true,false,ThreadId);
}
}
}
move_undo(board,nextbest_move,undo);
if (nextbest_value > best_value){
best_value = nextbest_value;
pv_cat(pv,new_pv,nextbest_move);
ASSERT(value_is_ok(best_value));
if (best_value > alpha) {
alpha = best_value;
}
}
}
} // end of horizon extensions
You can clearly see the extended searches going to seven plies over depth_best_move which is usually zero, or q-search only, as we are at depth == one. Sharpen_PV I borrowed from HIARCS but it is just the name of a yes or no variable here. The second block is to extend nextbest_move.
At the moment in build 370 the block above is bypassed by
Code: Select all
.
.
} // end of single reply extensions
goto cut; // Bypassing horizon extensions in this version
// [EdG: horizon extensions hack]
.
.
I have to rethink this whole structure.
Eelco