Upgrade to Bonanza 6.0
[bonanza.git] / search.c
index d7ca199..3ef962c 100644 (file)
--- a/search.c
+++ b/search.c
@@ -1,16 +1,16 @@
 #include <limits.h>
 #include <stdlib.h>
 #include <string.h>
+#include <math.h>
 #include <assert.h>
 #include "shogi.h"
 
-static void hist_add( tree_t * restrict ptree, int ply );
-static void hist_good( tree_t * restrict ptree, unsigned int move, int ply,
-                      int depth, int turn );
-static int detect_signals( tree_t * restrict ptree );
-static int detect_rep( tree_t * restrict ptree, int ply, int turn );
-static int rep_type( const tree_t * restrict ptree, int n, int i, int ply,
-                    int turn );
+static void CONV hist_add( tree_t * restrict ptree, int ply );
+static void CONV hist_good( tree_t * restrict ptree, unsigned int move,
+                           int ply, int depth, int turn );
+static int CONV detect_rep( tree_t * restrict ptree, int ply, int turn );
+static int CONV rep_type( const tree_t * restrict ptree, int n, int i, int ply,
+                         int turn );
 
 /* #define DBG_SEARCH */
 #if defined(DBG_SEARCH)
@@ -19,13 +19,13 @@ static int rep_type( const tree_t * restrict ptree, int n, int i, int ply,
 #  define DOut( ... )
 #endif
 
-int
+int CONV
 search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
        int ply, unsigned int state_node )
 {
   int value, alpha_old;
 
-  if ( ! ptree->nsuc_check[ply]        && depth < PLY_INC )
+  if ( ! ptree->nsuc_check[ply] && depth < PLY_INC )
     {
       return search_quies( ptree, alpha, beta, turn, ply, 1 );
     }
@@ -109,18 +109,6 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
            }
          break;
        }
-      
-      ptree->nreject_tried++;
-      if ( rejections_probe( ptree, turn, ply ) )
-       {
-         ptree->nreject_done++;
-         if ( alpha < score_inferior && score_inferior < beta )
-           {
-             pv_close( ptree, ply, turn ? white_superi_rep:black_superi_rep );
-           }
-         MOVE_CURR = MOVE_NA;
-         return score_inferior;
-       }
     }
 
   /*
@@ -143,52 +131,47 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
     if ( value <= alpha ) { return value; }
   }
 
-#if defined(NO_NULL_PRUNE)
-  state_node &= ~node_do_null;
-#endif
-
   ptree->amove_hash[ply] = 0;
+
 #if ! defined(MINIMUM)
   if ( ! ( game_status & flag_learning ) )
 #endif
     {
       /* probe the transposition table */
-      int tv = hash_probe( ptree, ply, depth, turn, alpha, beta, state_node );
-      switch ( tv )
+      switch ( hash_probe( ptree, ply, depth, turn, alpha, beta,
+                          &state_node ) )
        {
        case value_exact:
-         if ( alpha < HASH_VALUE )
+         MOVE_CURR = ptree->amove_hash[ply];
+         assert( ! IsMove(MOVE_CURR)
+                 || is_move_valid( ptree, MOVE_CURR, turn ) );
+         if ( ( state_node & node_do_hashcut ) && beta == alpha_old + 1 )
            {
-             if ( HASH_VALUE < beta ) { pv_close( ptree, ply, hash_hit ); }
-             else {
-               MOVE_CURR = ptree->amove_hash[ply];
-               assert( is_move_valid( ptree, MOVE_CURR, turn ) );
-             }
+             if ( alpha < HASH_VALUE
+                  && HASH_VALUE < beta ) { pv_close( ptree, ply, hash_hit ); }
+             return HASH_VALUE;
            }
-         return HASH_VALUE;
-         
+         break;
+
        case value_lower:
          MOVE_CURR = ptree->amove_hash[ply];
          assert( beta <= HASH_VALUE );
          assert( ! IsMove(MOVE_CURR)
                  || is_move_valid( ptree, MOVE_CURR, turn ) );
-         if ( beta == alpha_old + 1 ) { return HASH_VALUE; }
+         if ( ( state_node & node_do_hashcut )
+              && beta == alpha_old + 1 ) { return HASH_VALUE; }
          break;
          
        case value_upper:
          assert( HASH_VALUE <= alpha );
-         if ( beta == alpha_old + 1 ) { return HASH_VALUE; }
+         if ( ( state_node & node_do_hashcut )
+              && beta == alpha_old + 1 ) { return HASH_VALUE; }
          break;
-         
-       default:
-         state_node = tv;
        }
     }
 
   DOut( "\nhash cut passed" );
 
-  if ( depth >= REJEC_MIN_DEPTH ) { add_rejections( ptree, turn, ply ); }
-  
 
   if ( ! ptree->nsuc_check[ply] )
     {
@@ -204,10 +187,6 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
          if ( alpha < value
               && value < beta ) { pv_close( ptree, ply, mate_search ); }
       
-         if ( depth >= REJEC_MIN_DEPTH )
-           {
-             sub_rejections( ptree, turn, ply );
-           }
          assert( is_move_valid( ptree, MOVE_CURR, turn ) );
          return value;
        }
@@ -222,26 +201,20 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
          int null_depth, nrep;
          
          null_depth = NullDepth(depth);
-         nrep       = root_nrep + ply - 1;
+         nrep       = ptree->nrep + ply - 1;
 
          MOVE_CURR                   = MOVE_PASS;
          ptree->move_last[ply]       = ptree->move_last[ply-1];
-         ptree->stand_pat[ply+1]     = (short)( - ptree->stand_pat[ply] );
+         ptree->save_eval[ply+1]     = - ptree->save_eval[ply];
          ptree->nsuc_check[ply+1]    = 0;
          ptree->rep_board_list[nrep] = HASH_KEY;
          ptree->rep_hand_list[nrep]  = HAND_B;
          ptree->null_pruning_tried++;
 
          value = -search( ptree, -beta, 1-beta, Flip(turn), null_depth, ply+1,
-                          node_do_mate | node_do_recap | node_do_futile );
-         if ( SEARCH_ABORT )
-           {
-             if ( depth >= REJEC_MIN_DEPTH )
-               {
-                 sub_rejections( ptree, turn, ply );
-               }
-             return 0;
-           }
+                          node_do_mate | node_do_recap | node_do_futile
+                          | node_do_recursion | node_do_hashcut );
+         if ( SEARCH_ABORT ) { return 0; }
          
          if ( beta <= value )
            {
@@ -251,10 +224,6 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
                  hash_store( ptree, ply, depth, turn, value_lower,
                              value, MOVE_NA, state_node );
                }
-             if ( depth >= REJEC_MIN_DEPTH )
-               {
-                 sub_rejections( ptree, turn, ply );
-               }
              
              DOut( "\nnull move cut!\n" );
 
@@ -272,30 +241,29 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
        }
     }
 
-  /* recursive iterative-deepening for pv nodes */
-  if ( ! ptree->amove_hash[ply]
-       && depth >= 3*PLY_INC
-       && ( ( alpha == root_alpha && beta == root_beta )
-           || ( alpha == -root_beta && beta == -root_alpha ) ) )
+  /* recursive iterative-deepening */
+  if ( ! ptree->amove_hash[ply] && RecursionThreshold <= depth
+       && ( state_node & node_do_recursion ) )
     {
-      if ( depth >= REJEC_MIN_DEPTH ) { sub_rejections( ptree, turn, ply ); }
-      value = search( ptree, -score_bound, beta, turn, depth-2*PLY_INC, ply,
-                     node_do_mate | node_do_recap );
+      int new_depth      = RecursionDepth(depth);
+      int state_node_new = state_node & ~( node_do_mate | node_do_null
+                                          | node_do_hashcut );
+
+      value = search( ptree, alpha, beta, turn, new_depth, ply,
+                     state_node_new );
       if ( SEARCH_ABORT ) { return 0; }
 
-      if ( beta <= value && IsMove(MOVE_CURR) )
-       {
-         ptree->amove_hash[ply] = MOVE_CURR;
-       }
-      else if ( value < beta && ply <= (int)ptree->pv[ply-1].length )
+      if      ( beta  <= value ) { ptree->amove_hash[ply] = MOVE_CURR; }
+      else if ( alpha <  value )
        {
+         assert( ply <= (int)ptree->pv[ply-1].length );
          assert( -score_bound < value );
          ptree->amove_hash[ply] = ptree->pv[ply-1].a[ply];
        }
+      
       assert( ! ptree->amove_hash[ply]
              || is_move_valid( ptree, ptree->amove_hash[ply], turn ) );
 
-      if ( depth >= REJEC_MIN_DEPTH ) { add_rejections( ptree, turn, ply ); }
     }
 
   {
@@ -319,15 +287,15 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
 
       ptree->nsuc_check[ply+1] = 0U;
       state_node_new           = ( node_do_mate | node_do_recap | node_do_null
-                                  | node_do_futile );
+                                  | node_do_futile | node_do_recursion
+                                  | node_do_hashcut );
       extension                = 0;
       depth_reduced            = 0;
 
       hist_add( ptree, ply );
 
       /* decision of extensions */
-      if ( turn ? is_move_check_w( ptree, MOVE_CURR )
-                : is_move_check_b( ptree, MOVE_CURR ) )
+      if ( IsMoveCheck( ptree, turn, MOVE_CURR ) )
        {
          ptree->check_extension_done++;
          ptree->nsuc_check[ply+1]
@@ -353,7 +321,8 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
                          && I2PieceMove(MOVE_LAST) != silver ) ) )
        {
          ptree->recap_extension_done++;
-         state_node_new = node_do_null | node_do_mate | node_do_futile;
+         state_node_new = ( node_do_null | node_do_mate | node_do_futile
+                            | node_do_recursion | node_do_hashcut );
          if ( ! I2IsPromote(MOVE_CURR)
               && I2PieceMove(MOVE_LAST) == UToCap(MOVE_LAST) )
            {
@@ -368,6 +337,7 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
 
       /* reductions */
       if ( PLY_INC <= new_depth
+          && first_move_expanded
           && ! ( state_node & node_mate_threat )
           && ! ptree->nsuc_check[ply]
           && ! UToCap(MOVE_CURR)
@@ -381,15 +351,14 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
          unsigned int triedx8 = ( ptree->hist_tried[key] + 2 ) * 8U;
 
          if ( beta != alpha_old + 1 ) {
-           
-           if      ( good * 62U < triedx8 ) { depth_reduced = PLY_INC * 4/2; }
-           else if ( good * 46U < triedx8 ) { depth_reduced = PLY_INC * 3/2; }
-           else if ( good * 34U < triedx8 ) { depth_reduced = PLY_INC * 2/2; }
+
+           if      ( good *160U < triedx8 ) { depth_reduced = PLY_INC * 3/2; }
+           else if ( good * 50U < triedx8 ) { depth_reduced = PLY_INC * 2/2; }
            else if ( good * 19U < triedx8 ) { depth_reduced = PLY_INC * 1/2; }
-           
+
          } else {
            
-           if      ( good * 62U < triedx8 ) { depth_reduced = PLY_INC * 4/2; }
+           if      ( good * 75U < triedx8 ) { depth_reduced = PLY_INC * 4/2; }
            else if ( good * 46U < triedx8 ) { depth_reduced = PLY_INC * 3/2; }
            else if ( good * 30U < triedx8 ) { depth_reduced = PLY_INC * 2/2; }
            else if ( good * 12U < triedx8 ) { depth_reduced = PLY_INC * 1/2; }
@@ -397,7 +366,7 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
 
          new_depth -= depth_reduced;
        }
-      
+
       /* futility pruning */
       if ( ! ptree->nsuc_check[ply+1]
           && ! ptree->nsuc_check[ply]
@@ -409,7 +378,7 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
          if      ( 2*PLY_INC <= new_depth ) { bound -= EFUTIL_MG2; }
          else if ( 1*PLY_INC <= new_depth ) { bound -= EFUTIL_MG1; }
          
-         if ( eval_max_score( ptree, MOVE_CURR, ptree->stand_pat[ply],
+         if ( eval_max_score( ptree, MOVE_CURR, ptree->save_eval[ply],
                               turn, diff ) <= bound )
            {
              first_move_expanded += 1;
@@ -419,6 +388,22 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
 
       DOut( ", futil passed" );
 
+      if ( new_depth < 2*PLY_INC
+          && ! ptree->nsuc_check[ply]
+          && ! ptree->nsuc_check[ply+1]
+          && ! UToCap(MOVE_CURR)
+          && ! ( I2IsPromote(MOVE_CURR)
+                   && I2PieceMove(MOVE_CURR) != silver )
+           && ptree->amove_hash[ply]  != MOVE_CURR
+          && ptree->killers[ply].no1 != MOVE_CURR
+          && ptree->killers[ply].no2 != MOVE_CURR
+          && beta == alpha_old + 1
+          && swap( ptree, MOVE_CURR, -1, 0, turn ) <= -1 )
+       {
+         first_move_expanded += 1;
+         continue;
+       }
+
       MakeMove( turn, MOVE_CURR, ply );
       if ( I2From(MOVE_CURR) < nsquare
           && ! ptree->nsuc_check[ply]
@@ -430,15 +415,13 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
 
       if ( ! ptree->nsuc_check[ply+1] && ! ptree->nsuc_check[ply] )
        {
-         evaluate( ptree, ply+1, Flip(turn) );
-         assert( ptree->stand_pat[ply] != score_bound );
+         int score = -evaluate( ptree, ply+1, Flip(turn) );
+         assert( ptree->save_eval[ply] != INT_MAX );
 
          /* futility pruning */
-         if ( ( new_depth < PLY_INC && - ptree->stand_pat[ply+1] <= alpha )
-              || ( new_depth < 2*PLY_INC
-                   && - ptree->stand_pat[ply+1] <= alpha - EFUTIL_MG1 )
-              || ( new_depth < 3*PLY_INC
-                   && - ptree->stand_pat[ply+1] <= alpha - EFUTIL_MG2 ) )
+         if ( ( new_depth < PLY_INC && score <= alpha )
+              || ( new_depth < 2*PLY_INC && score <= alpha - EFUTIL_MG1 )
+              || ( new_depth < 3*PLY_INC && score <= alpha - EFUTIL_MG2 ) )
            {
              first_move_expanded += 1;
              UnMakeMove( turn, MOVE_CURR, ply );
@@ -446,18 +429,7 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
            }
        }
 
-      if ( depth_reduced )
-       {
-         value = -search( ptree, -alpha-1, -alpha, Flip(turn), new_depth,
-                          ply + 1, state_node_new );
-         if ( ! SEARCH_ABORT && alpha < value )
-           {
-             new_depth += depth_reduced;
-             value = -search( ptree, -beta, -alpha, Flip(turn), new_depth,
-                              ply+1, state_node_new );
-           }
-       }
-      else if ( ! first_move_expanded )
+      if ( ! first_move_expanded )
        {
          value = -search( ptree, -beta, -alpha, Flip(turn), new_depth, ply+1,
                           state_node_new );
@@ -465,20 +437,21 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
       else {
        value = -search( ptree, -alpha-1, -alpha, Flip(turn), new_depth,
                         ply + 1, state_node_new );
+       if ( ! SEARCH_ABORT && alpha < value && depth_reduced )
+         {
+           new_depth += depth_reduced;
+           value = -search( ptree, -alpha-1, -alpha, Flip(turn), new_depth,
+                            ply+1, state_node_new );
+         }
        if ( ! SEARCH_ABORT && alpha < value && beta != alpha+1 )
          {
            value = -search( ptree, -beta, -alpha, Flip(turn), new_depth,
                             ply + 1, state_node_new );
          }
       }
-
       if ( SEARCH_ABORT )
        {
          UnMakeMove( turn, MOVE_CURR, ply );
-         if ( depth >= REJEC_MIN_DEPTH )
-           {
-             sub_rejections( ptree, turn, ply );
-           }
          return 0;
        }
 
@@ -488,11 +461,11 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
        {
          if ( new_depth < PLY_INC
               && ! ptree->nsuc_check[ply+1]
-              && ptree->stand_pat[ply] != score_bound )
+              && ptree->save_eval[ply] != INT_MAX )
            {
              check_futile_score_quies( ptree, MOVE_CURR,
-                                       ptree->stand_pat[ply],
-                                       -ptree->stand_pat[ply+1], turn );
+                                       ptree->save_eval[ply],
+                                       -ptree->save_eval[ply+1], turn );
            }
 
          if ( beta <= value )
@@ -506,11 +479,6 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
              ptree->fail_high++;
              if ( ! first_move_expanded ) { ptree->fail_high_first++; }
              
-             if ( depth >= REJEC_MIN_DEPTH )
-               {
-                 sub_rejections( ptree, turn, ply );
-               }
-
              assert( is_move_valid( ptree, MOVE_CURR, turn ) );
              return value;
            }
@@ -539,11 +507,6 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
                {
                  if ( beta <= value )
                    {
-                     if ( depth >= REJEC_MIN_DEPTH )
-                       {
-                         sub_rejections( ptree, turn, ply );
-                       }
-
                      hash_store( ptree, ply, depth, turn, value_lower,
                                  value, MOVE_CURR, state_node );
                      
@@ -564,8 +527,6 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
 
     DOut( "\nall searched (%" PRIu64 ")\n", ptree->node_searched );
 
-    if ( depth >= REJEC_MIN_DEPTH ) { sub_rejections( ptree, turn, ply ); }
-
     if ( ! first_move_expanded )
       {
 #if ! defined(MINIMUM)
@@ -617,7 +578,7 @@ search( tree_t * restrict ptree, int alpha, int beta, int turn, int depth,
 
 
 #if defined(TLP)
-int
+int CONV
 tlp_search( tree_t * restrict ptree, int alpha, int beta, int turn,
            int depth, int ply, unsigned int state_node )
 {
@@ -630,11 +591,17 @@ tlp_search( tree_t * restrict ptree, int alpha, int beta, int turn,
 
   for ( ;; ) {
     lock( & ptree->tlp_ptree_parent->tlp_lock );
+    if ( ptree->tlp_abort )
+      {
+       unlock( & ptree->tlp_ptree_parent->tlp_lock );
+       return 0;
+      }
     if ( ptree->nsuc_check[ply] )
       {
        iret = gen_next_evasion( ptree->tlp_ptree_parent, ply, turn );
       }
     else { iret = gen_next_move( ptree->tlp_ptree_parent, ply, turn ); }
+
     MOVE_CURR = ptree->tlp_ptree_parent->current_move[ply];
     hist_add( ptree->tlp_ptree_parent, ply );
     unlock( & ptree->tlp_ptree_parent->tlp_lock );
@@ -642,12 +609,12 @@ tlp_search( tree_t * restrict ptree, int alpha, int beta, int turn,
 
     ptree->nsuc_check[ply+1] = 0U;
     state_node_new           = ( node_do_mate | node_do_recap | node_do_null
-                                | node_do_futile );
+                                | node_do_futile | node_do_recursion
+                                | node_do_hashcut );
     extension                = 0;
     depth_reduced            = 0;
 
-    if ( turn ? is_move_check_w( ptree, MOVE_CURR )
-              : is_move_check_b( ptree, MOVE_CURR ) )
+    if ( IsMoveCheck( ptree, turn, MOVE_CURR ) )
       {
        ptree->check_extension_done++;
        ptree->nsuc_check[ply+1]
@@ -666,7 +633,8 @@ tlp_search( tree_t * restrict ptree, int alpha, int beta, int turn,
                        && I2PieceMove(MOVE_LAST) != silver ) ) )
       {
        ptree->recap_extension_done++;
-       state_node_new = node_do_null | node_do_mate | node_do_futile;
+       state_node_new = ( node_do_null | node_do_mate | node_do_futile
+                          | node_do_recursion | node_do_hashcut );
        if ( ! I2IsPromote(MOVE_CURR)
             && I2PieceMove(MOVE_LAST) == UToCap(MOVE_LAST) )
          {
@@ -693,14 +661,13 @@ tlp_search( tree_t * restrict ptree, int alpha, int beta, int turn,
 
          if ( beta != alpha_old + 1 ) {
            
-           if      ( good * 62U < triedx8 ) { depth_reduced = PLY_INC * 4/2; }
-           else if ( good * 46U < triedx8 ) { depth_reduced = PLY_INC * 3/2; }
-           else if ( good * 34U < triedx8 ) { depth_reduced = PLY_INC * 2/2; }
+           if      ( good *160U < triedx8 ) { depth_reduced = PLY_INC * 3/2; }
+           else if ( good * 50U < triedx8 ) { depth_reduced = PLY_INC * 2/2; }
            else if ( good * 19U < triedx8 ) { depth_reduced = PLY_INC * 1/2; }
            
          } else {
            
-           if      ( good * 62U < triedx8 ) { depth_reduced = PLY_INC * 4/2; }
+           if      ( good * 75U < triedx8 ) { depth_reduced = PLY_INC * 4/2; }
            else if ( good * 46U < triedx8 ) { depth_reduced = PLY_INC * 3/2; }
            else if ( good * 30U < triedx8 ) { depth_reduced = PLY_INC * 2/2; }
            else if ( good * 12U < triedx8 ) { depth_reduced = PLY_INC * 1/2; }
@@ -719,7 +686,7 @@ tlp_search( tree_t * restrict ptree, int alpha, int beta, int turn,
        if      ( 2*PLY_INC <= new_depth ) { bound -= EFUTIL_MG2; }
        else if ( 1*PLY_INC <= new_depth ) { bound -= EFUTIL_MG1; }
        
-       if ( eval_max_score( ptree, MOVE_CURR, ptree->stand_pat[ply],
+       if ( eval_max_score( ptree, MOVE_CURR, ptree->save_eval[ply],
                             turn, diff ) <= bound )
          {
            continue;
@@ -737,15 +704,13 @@ tlp_search( tree_t * restrict ptree, int alpha, int beta, int turn,
 
     if ( ! ptree->nsuc_check[ply+1] && ! ptree->nsuc_check[ply] )
       {
-       evaluate( ptree, ply+1, Flip(turn) );
-       assert( ptree->stand_pat[ply] != score_bound );
+       int score = -evaluate( ptree, ply+1, Flip(turn) );
+       assert( ptree->save_eval[ply] != INT_MAX );
 
        /* futility pruning */
-       if ( ( new_depth < PLY_INC && - ptree->stand_pat[ply+1] <= alpha )
-            || ( new_depth < 2*PLY_INC
-                 && - ptree->stand_pat[ply+1] <= alpha - EFUTIL_MG1 )
-            || ( new_depth < 3*PLY_INC
-                 && - ptree->stand_pat[ply+1] <= alpha - EFUTIL_MG2 ) )
+       if ( ( new_depth < PLY_INC && score <= alpha )
+            || ( new_depth < 2*PLY_INC && score <= alpha - EFUTIL_MG1 )
+            || ( new_depth < 3*PLY_INC && score <= alpha - EFUTIL_MG2 ) )
          {
            UnMakeMove( turn, MOVE_CURR, ply );
            continue;
@@ -803,14 +768,52 @@ tlp_search( tree_t * restrict ptree, int alpha, int beta, int turn,
 }
 #endif /* TLP */
 
+void CONV
+pv_close( tree_t * restrict ptree, int ply, int type )
+{
+  ptree->pv[ply-1].a[ply-1] = (ptree)->current_move[ply-1];
+  ptree->pv[ply-1].length   = (unsigned char)(ply-1);
+  ptree->pv[ply-1].type     = (unsigned char)type;
+  ptree->pv[ply-1].depth    = (unsigned char)iteration_depth;
+}
+
+void CONV
+pv_copy( tree_t * restrict ptree, int ply )
+{
+  memcpy( &(ptree->pv[ply-1].a[ply]), &(ptree->pv[ply].a[ply]),
+         ( ptree->pv[ply].length-ply+1 ) * sizeof(unsigned int) );
+  ptree->pv[ply-1].type     = ptree->pv[ply].type;
+  ptree->pv[ply-1].length   = ptree->pv[ply].length;
+  ptree->pv[ply-1].depth    = ptree->pv[ply].depth;
+  ptree->pv[ply-1].a[ply-1] = ptree->current_move[ply-1];
+}
+
 
-static int
+int CONV
 detect_signals( tree_t * restrict ptree )
 {
   unsigned int tnow, telapsed, tpondered, tsearched, tcount, tlimit, tmax;
-  unsigned int tmax_limit_count, tlimit_count, u;
+  unsigned int tlimit_count, u;
   int iret, easy_time, last_value, stable;
 
+#if defined(DFPN_CLIENT)
+  int is_first_move_skipped = 0;
+#endif
+
+#if defined(DFPN_CLIENT)
+  /* probe results from DFPN server */
+  if ( dfpn_client_flag_read )
+    {
+      dfpn_client_check_results();
+      if ( dfpn_client_move_unlocked != MOVE_NA ) { return 1; }
+      if ( root_move_list[root_index].dfpn_cresult == dfpn_client_win )
+       {
+         is_first_move_skipped = 1;
+       }
+    }
+#endif
+
+
   if ( ! ( game_status & flag_nopeek ) )
     {
       /* peek input-buffer to find a command */
@@ -823,7 +826,7 @@ detect_signals( tree_t * restrict ptree )
       else if ( iret == -2 )
        {
          out_warning( "%s", str_error );
-         ShutdownClient;
+         ShutdownAll();
        }
       else if ( game_status & flag_quit ) { return 1; } /* EOF */
       else if ( iret )
@@ -840,7 +843,7 @@ detect_signals( tree_t * restrict ptree )
            {
              out_warning( "%s", str_error );
              next_cmdline( 1 );
-             ShutdownClient;
+             ShutdownAll();
            }
          else if ( iret == 1 ) { next_cmdline( 1 ); }
 
@@ -872,10 +875,11 @@ detect_signals( tree_t * restrict ptree )
     }
 #endif
 
-#if defined(MNJ_LAN)
-  if ( sckt_mnj != SCKT_NULL && 500U < tnow - time_last_send )
+#if defined(USI)
+  if ( usi_mode != usi_off && 1000U + usi_time_out_last < tnow )
     {
       uint64_t nodes;
+      double dnps;
 
 #  if defined(TLP)
       lock( &tlp_lock );
@@ -885,12 +889,28 @@ detect_signals( tree_t * restrict ptree )
       nodes = ptree->node_searched;
 #  endif
 
-      if ( sckt_out( sckt_mnj, "pid=%d n=%" PRIu64 "\n", mnj_posi_id,
-                    nodes ) < 0 )
-       {
-         game_status |= flag_search_error;
-         return 1;
-       }
+      dnps = (double)nodes * 1000.0 / (double)( tnow - time_turn_start );
+      USIOut( "info time %u nodes %" PRIu64 " nps %d\n",
+             tnow, nodes, (unsigned int)dnps );
+             
+      usi_time_out_last = tnow;
+    }
+#endif
+
+#if defined(MNJ_LAN)
+  if ( sckt_mnj != SCKT_NULL && 500U + time_last_send < tnow )
+    {
+      uint64_t nodes;
+      
+#  if defined(TLP)
+      lock( &tlp_lock );
+      nodes = tlp_count_node( tlp_atree_work );
+      unlock( &tlp_lock );
+#  else
+      nodes = ptree->node_searched;
+#  endif
+      
+      MnjOut( "pid=%d n=%" PRIu64 "\n", mnj_posi_id, nodes );
     }
 #endif
 
@@ -935,12 +955,10 @@ detect_signals( tree_t * restrict ptree )
   if ( tlimit != tmax )
     {
       tcount           = tsearched;
-      tmax_limit_count = tmax;
       tlimit_count     = tlimit;
     }
   else {
     tcount           = telapsed;
-    tmax_limit_count = tmax   + tpondered;
     tlimit_count     = tlimit + tpondered;
   }
 
@@ -953,22 +971,6 @@ detect_signals( tree_t * restrict ptree )
   if ( stable && tcount > tlimit ) { return 1; }
   
   if ( stable
-       && ( tmax_limit_count * 3U < ( time_last_search - time_start ) * 5U ) )
-    {
-#if defined(DBG_EASY)
-      if ( ! easy_move )
-       {
-         Out( "  The search can be terminated "
-              "before it reaches time-limit.\n" );
-         easy_move = ptree->pv[0].a[1];
-       }
-#else
-      Out( "  The search is terminated before it reaches time-limit.\n" );
-      return 1;
-#endif
-    }
-
-  if ( stable
        && easy_abs > abs( last_value )
        && easy_min < last_value - easy_value
        && easy_max > last_value - easy_value )
@@ -998,7 +1000,7 @@ detect_signals( tree_t * restrict ptree )
       else if ( tsearched + 500U > u ) { easy_time = 1; }
     }
 
-  /* renew node_per_second */
+  /* update node_per_second */
   {
     double dn, dd;
 
@@ -1010,7 +1012,7 @@ detect_signals( tree_t * restrict ptree )
     else                                 { node_per_second  = u; }
   }
 
-  /* renew node_next_signal */
+  /* update node_next_signal */
   if ( ! ( game_status & flag_pondering ) && root_nmove == 1 )
     {
       u = 2000U - time_response;
@@ -1025,203 +1027,31 @@ detect_signals( tree_t * restrict ptree )
     }
   else { node_next_signal = node_per_second / 32U; }
 
-  /* renew time_last_check and node_last_check */
+  /* update time_last_check and node_last_check */
   time_last_check = tnow;
   node_last_check = 0;
 
-       
-  return 0;
-}
-
 
-int
-is_move_check_b( const tree_t * restrict ptree, unsigned int move )
-{
-  const int from = (int)I2From(move);
-  const int to   = (int)I2To(move);
-  int is_check, ipiece_move, idirec;
-  bitboard_t bb;
-
-  is_check = 0;
-
-  if ( from >= nsquare ) { ipiece_move = From2Drop(from); }
-  else {
-    ipiece_move = (int)I2PieceMove(move);
-    if ( I2IsPromote(move) ) { ipiece_move += promote; }
-    
-    idirec = (int)adirec[SQ_WKING][from];
-    if ( idirec && idirec != (int)adirec[SQ_WKING][to]
-        && is_pinned_on_white_king( ptree, from, idirec ) )
-      {
-       is_check = 1;
-       goto end;
-      }
-  }
-  
-  switch ( ipiece_move )
+#if defined(DFPN_CLIENT)
+  if ( is_first_move_skipped )
     {
-    case pawn:
-      if ( BOARD[to-nfile] == -king ) { is_check = 1; }
-      break;
-         
-    case lance:
-      AttackBLance( bb, to );
-      if ( BBContract( bb, BB_WKING ) ) { is_check = 1; }
-      break;
-      
-    case knight:
-      if ( BBContract(abb_b_knight_attacks[to],BB_WKING) ) { is_check = 1; }
-      break;
-      
-    case silver:
-      if ( BBContract(abb_b_silver_attacks[to],BB_WKING) ) { is_check = 1; }
-      break;
-      
-    case gold:        case pro_pawn:
-    case pro_lance:    case pro_knight:
-    case pro_silver:
-      if ( BBContract(abb_b_gold_attacks[to],BB_WKING) ) { is_check = 1; }
-      break;
-      
-    case bishop:
-      AttackBishop( bb, to );
-      if ( BBContract( bb, BB_WKING ) ) { is_check = 1; }
-      break;
-      
-    case rook:
-      AttackRook( bb, to );
-      if ( BBContract( bb, BB_WKING ) ) { is_check = 1; }
-      break;
-      
-    case king:
-      break;
-
-    case horse:
-      AttackHorse( bb, to );
-      if ( BBContract( bb, BB_WKING ) ) { is_check = 1; }
-      break;
-      
-    default:
-      assert( ipiece_move == dragon );
-      AttackDragon( bb, to );
-      if ( BBContract( bb, BB_WKING ) ) { is_check = 1; }
-      break;
-    }
-
- end:
-  return is_check;
-}
-
-
-int
-is_move_check_w( const tree_t * restrict ptree, unsigned int move )
-{
-  const int from = (int)I2From(move);
-  const int to   = (int)I2To(move);
-  int is_check, ipiece_move, idirec;
-  bitboard_t bb;
-
-  is_check = 0;
-
-  if ( from >= nsquare ) { ipiece_move = From2Drop(from); }
-  else {
-    ipiece_move = (int)I2PieceMove(move);
-    if ( I2IsPromote(move) ) { ipiece_move += promote; }
-    
-    idirec = (int)adirec[SQ_BKING][from];
-    if ( idirec && idirec != (int)adirec[SQ_BKING][to]
-        && is_pinned_on_black_king( ptree, from, idirec ) )
-      {
-       is_check = 1;
-       goto end;
-      }
-  }
-  
-  switch ( ipiece_move )
-    {
-    case pawn:
-      if ( BOARD[to+nfile] == king ) { is_check = 1; }
-      break;
-      
-    case lance:
-      AttackWLance( bb, to );
-      if ( BBContract( bb, BB_BKING ) ) { is_check = 1; }
-      break;
-      
-    case knight:
-      if ( BBContract(abb_w_knight_attacks[to],BB_BKING) ) { is_check = 1; }
-      break;
-      
-    case silver:
-      if ( BBContract(abb_w_silver_attacks[to],BB_BKING) ) { is_check = 1; }
-      break;
-      
-    case gold:        case pro_pawn:
-    case pro_lance:   case pro_knight:
-    case pro_silver:
-      if ( BBContract(abb_w_gold_attacks[to],BB_BKING) ) { is_check = 1; }
-      break;
-      
-    case bishop:
-      AttackBishop( bb, to );
-      if ( BBContract( bb, BB_BKING ) ) { is_check = 1; }
-      break;
-      
-    case rook:
-      AttackRook( bb, to );
-      if ( BBContract( bb, BB_BKING ) ) { is_check = 1; }
-      break;
-
-    case king:
-      break;
-
-    case horse:
-      AttackHorse( bb, to );
-      if ( BBContract( bb, BB_BKING ) ) { is_check = 1; }
-      break;
-      
-    default:
-      assert( ipiece_move == dragon );
-      AttackDragon( bb, to );
-      if ( BBContract( bb, BB_BKING ) ) { is_check = 1; }
-      break;
+      game_status |= flag_skip_root_move;
+      return 1;
     }
-
- end:
-  return is_check;
-}
-
-
-void
-pv_close( tree_t * restrict ptree, int ply, int type )
-{
-  ptree->pv[ply-1].a[ply-1] = (ptree)->current_move[ply-1];
-  ptree->pv[ply-1].length   = (unsigned char)(ply-1);
-  ptree->pv[ply-1].type     = (unsigned char)type;
-  ptree->pv[ply-1].depth    = (unsigned char)iteration_depth;
-}
-
-
-void
-pv_copy( tree_t * restrict ptree, int ply )
-{
-  memcpy( &(ptree->pv[ply-1].a[ply]), &(ptree->pv[ply].a[ply]),
-         ( ptree->pv[ply].length-ply+1 ) * sizeof(unsigned int) );
-  ptree->pv[ply-1].type     = ptree->pv[ply].type;
-  ptree->pv[ply-1].length   = ptree->pv[ply].length;
-  ptree->pv[ply-1].depth    = ptree->pv[ply].depth;
-  ptree->pv[ply-1].a[ply-1] = ptree->current_move[ply-1];
+#endif
+       
+  return 0;
 }
 
 
-static int
+static int CONV
 detect_rep( tree_t * restrict ptree, int ply, int turn )
 {
   if ( ply < 4 ) { return detect_repetition( ptree, ply, turn, 2 ); }
   else {
     int n, i, imin, iret;
 
-    n    = root_nrep + ply - 1;
+    n    = ptree->nrep + ply - 1;
     imin = n - REP_MAX_PLY;
     if ( imin < 0 ) { imin = 0; }
 
@@ -1237,7 +1067,7 @@ detect_rep( tree_t * restrict ptree, int ply, int turn )
 }
 
 
-static int
+static int CONV
 rep_type( const tree_t * restrict ptree, int n, int i, int ply, int turn )
 {
   const unsigned int hand1 = HAND_B;
@@ -1267,7 +1097,7 @@ rep_type( const tree_t * restrict ptree, int n, int i, int ply, int turn )
 }
 
 
-static void
+static void CONV
 hist_add( tree_t * restrict ptree, int ply )
 {
   if ( ptree->nsuc_check[ply] ) { return; }
@@ -1280,7 +1110,7 @@ hist_add( tree_t * restrict ptree, int ply )
 }
 
 
-static void
+static void CONV
 hist_good( tree_t * restrict ptree, unsigned int move_good, int ply,
           int depth, int turn )
 {