@@ -646,6 +646,7 @@ fn search<NODE: NodeType>(
646646
647647 // Singular Extensions (SE)
648648 let mut extension = 0 ;
649+ let mut singular_score = Score :: NONE ;
649650
650651 if !NODE :: ROOT && !excluded && potential_singularity {
651652 debug_assert ! ( is_valid( tt_score) ) ;
@@ -656,29 +657,29 @@ fn search<NODE: NodeType>(
656657 let singular_depth = ( depth - 1 ) / 2 ;
657658
658659 td. stack [ ply] . excluded = tt_move;
659- let score = search :: < NonPV > ( td, singular_beta - 1 , singular_beta, singular_depth, cut_node, ply) ;
660+ singular_score = search :: < NonPV > ( td, singular_beta - 1 , singular_beta, singular_depth, cut_node, ply) ;
660661 td. stack [ ply] . excluded = Move :: NULL ;
661662
662663 if td. shared . status . get ( ) == Status :: STOPPED {
663664 return Score :: ZERO ;
664665 }
665666
666- if score < singular_beta {
667+ if singular_score < singular_beta {
667668 let double_margin =
668669 204 * NODE :: PV as i32 - 16 * tt_move. is_quiet ( ) as i32 - 16 * correction_value. abs ( ) / 128 ;
669670 let triple_margin =
670671 257 * NODE :: PV as i32 - 16 * tt_move. is_quiet ( ) as i32 - 15 * correction_value. abs ( ) / 128 + 32 ;
671672
672673 extension = 1 ;
673- extension += ( score < singular_beta - double_margin) as i32 ;
674- extension += ( score < singular_beta - triple_margin) as i32 ;
674+ extension += ( singular_score < singular_beta - double_margin) as i32 ;
675+ extension += ( singular_score < singular_beta - triple_margin) as i32 ;
675676 }
676677 // Multi-Cut
677- else if score >= beta && !is_decisive ( score ) {
678- return ( 2 * score + beta) / 3 ;
678+ else if singular_score >= beta && !is_decisive ( singular_score ) {
679+ return ( 2 * singular_score + beta) / 3 ;
679680 }
680681 // Negative Extensions
681- else if score > tt_score {
682+ else if singular_score > tt_score {
682683 tt_move = Move :: NULL ;
683684 } else if tt_score >= beta {
684685 extension = -2 ;
@@ -698,6 +699,7 @@ fn search<NODE: NodeType>(
698699 let mut skip_quiets = false ;
699700 let mut current_search_count = 0 ;
700701 let mut alpha_raises = 0 ;
702+ let mut tt_move_score = Score :: NONE ;
701703
702704 while let Some ( mv) = move_picker. next :: < NODE > ( td, skip_quiets, ply) {
703705 if mv == td. stack [ ply] . excluded {
@@ -824,6 +826,11 @@ fn search<NODE: NodeType>(
824826 reduction += 1515 ;
825827 }
826828
829+ if is_valid ( tt_move_score) && is_valid ( singular_score) {
830+ let margin = tt_move_score - singular_score;
831+ reduction += ( 512 * ( margin - 160 ) / 128 ) . clamp ( 0 , 2048 ) ;
832+ }
833+
827834 if !NODE :: PV && td. stack [ ply - 1 ] . reduction > reduction + 485 {
828835 reduction += 129 ;
829836 }
@@ -882,6 +889,11 @@ fn search<NODE: NodeType>(
882889 reduction += 1360 ;
883890 }
884891
892+ if is_valid ( tt_move_score) && is_valid ( singular_score) {
893+ let margin = tt_move_score - singular_score;
894+ reduction += ( 400 * ( margin - 160 ) / 128 ) . clamp ( 0 , 2048 ) ;
895+ }
896+
885897 if mv == tt_move {
886898 reduction -= 3281 ;
887899 }
@@ -947,6 +959,10 @@ fn search<NODE: NodeType>(
947959 }
948960 }
949961
962+ if mv == tt_move {
963+ tt_move_score = score;
964+ }
965+
950966 if score > best_score {
951967 best_score = score;
952968
0 commit comments