Upgrade to Bonanza 6.0
[bonanza.git] / iterate.c
index d940814..1a684bc 100644 (file)
--- a/iterate.c
+++ b/iterate.c
@@ -4,46 +4,34 @@
 #include <stdlib.h>
 #include "shogi.h"
 
-static void adjust_fmg( void );
-static int ini_hash( void );
-static int set_root_alpha( int nfail_low, int root_alpha_old );
-static int set_root_beta( int nfail_high, int root_beta_old );
-static int is_answer_right( unsigned int move );
-static const char *str_fail_high( int turn, int nfail_high );
+static void CONV adjust_fmg( void );
+static int CONV set_root_alpha( int nfail_low, int root_alpha_old );
+static int CONV set_root_beta( int nfail_high, int root_beta_old );
+static int CONV is_answer_right( unsigned int move );
+static int CONV rep_book_prob( tree_t * restrict ptree );
+static const char * CONV str_fail_high( int turn, int nfail_high );
 
 
-static int rep_book_prob( tree_t * restrict ptree )
+int CONV
+iterate( tree_t * restrict ptree )
 {
-  int i;
-
-  for ( i = root_nrep - 2; i >= 0; i -= 2 )
-    if ( ptree->rep_board_list[i] == HASH_KEY
-        && ptree->rep_hand_list[i] == HAND_B )
-      {
-       Out( "- book is ignored due to a repetition.\n" );
-       return 1;
-      }
-
-  return 0;
-}
-
-
-int
-iterate( tree_t * restrict ptree, int flag )
-{
-  int value, iret, ply, is_hash_learn_stored;
+  int value, iret, ply;
   unsigned int cpu_start;
   int right_answer_made;
 
   /* probe the opening book */
-  if ( pf_book != NULL && n_nobook_move < 7 && ! rep_book_prob( ptree  ) )
+  if ( pf_book != NULL
+#if defined(USI) || defined(MNJ_LAN)
+       && moves_ignore[0] == MOVE_NA
+#endif
+       && ! rep_book_prob( ptree ) )
     {
       int is_book_hit, i;
       unsigned int elapsed;
-
+      
       is_book_hit = book_probe( ptree );
       if ( is_book_hit < 0 ) { return is_book_hit; }
-
+      
       iret = get_elapsed( &elapsed );
       if ( iret < 0 ) { return iret; }
 
@@ -54,33 +42,71 @@ iterate( tree_t * restrict ptree, int flag )
          pv_close( ptree, 2, book_hit );
          last_pv         = ptree->pv[1];
          last_root_value = 0;
-         n_nobook_move   = 0;
          if ( ! ( game_status & flag_puzzling ) )
            {
-             for ( i = 0; i < HIST_SIZE; i++ )
+             for ( i = 0; i < (int)HIST_SIZE; i++ )
                {
                  ptree->hist_good[i]  /= 256U;
                  ptree->hist_tried[i] /= 256U;
                }
            }
+         MnjOut( "pid=%d move=%s n=0 v=0e final%s\n",
+                 mnj_posi_id, str_CSA_move(ptree->pv[1].a[1]),
+                 ( mnj_depth_stable == INT_MAX ) ? "" : " stable" );
+
 
-         MnjOut( "pid=%d move=%s v=0b n=0 confident\n", mnj_posi_id,
-                 str_CSA_move(ptree->pv[1].a[1]) );
+#if defined(USI)
+         if ( usi_mode != usi_off )
+           {
+             char str_usi[6];
+             csa2usi( ptree, str_CSA_move(ptree->pv[1].a[1]), str_usi );
+             USIOut( "info depth 1 score cp 0 nodes 0 pv %s\n", str_usi );
+           }                 
+#endif
 
          return 1;
        }
-      if ( ! ( game_status & ( flag_puzzling | flag_pondering ) ) )
+    }
+
+  /* detect inaniwa tactics */
+#if defined(INANIWA_SHIFT)
+  if ( ! inaniwa_flag && 19 < ptree->nrep )
+    {
+      if ( root_turn == white
+          && ( BOARD[A7]==-pawn || BOARD[A6]==-pawn || BOARD[A5]==-pawn )
+          && BOARD[B7] == -pawn && BOARD[C7] == -pawn
+          && BOARD[D7] == -pawn && BOARD[E7] == -pawn
+          && BOARD[F7] == -pawn && BOARD[G7] == -pawn
+          && BOARD[H7] == -pawn
+          && ( BOARD[I7]==-pawn || BOARD[I6]==-pawn || BOARD[I5]==-pawn ) )
+       {
+         Out( "\nINANIWA SHIFT TURNED ON (BLACK)\n\n" );
+         inaniwa_flag = 1;
+         ehash_clear();
+         if ( ini_trans_table() < 0 ) { return -1; }
+       }
+
+      if ( root_turn == black
+          && ( BOARD[A3]==pawn || BOARD[A4]==pawn || BOARD[A5] == pawn )
+          && BOARD[B3] == pawn && BOARD[C3] == pawn
+          && BOARD[D3] == pawn && BOARD[E3] == pawn
+          && BOARD[F3] == pawn && BOARD[G3] == pawn
+          && BOARD[H3] == pawn
+          && ( BOARD[I3]==pawn || BOARD[I4]==pawn || BOARD[I5]==pawn ) )
        {
-         n_nobook_move += 1;
+         Out( "\nINANIWA SHIFT TURNED ON (WHITE)\n\n" );
+         inaniwa_flag = 2;
+         ehash_clear();
+         if ( ini_trans_table() < 0 ) { return -1; }
        }
     }
+#endif
+  
 
   /* initialize variables */
   if ( get_cputime( &cpu_start ) < 0 ) { return -1; }
 
   ptree->node_searched         =  0;
-  ptree->nreject_done          =  0;
-  ptree->nreject_tried         =  0;
   ptree->null_pruning_done     =  0;
   ptree->null_pruning_tried    =  0;
   ptree->check_extension_done  =  0;
@@ -103,6 +129,8 @@ iterate( tree_t * restrict ptree, int flag )
   ptree->fail_high             =  0;
   ptree->fail_high_first       =  0;
   ptree->current_move[0]       =  0;
+  ptree->save_eval[0]          =  INT_MAX;
+  ptree->save_eval[1]          =  INT_MAX;
   ptree->pv[0].a[0]            =  0;
   ptree->pv[0].a[1]            =  0;
   ptree->pv[0].depth           =  0;
@@ -111,15 +139,14 @@ iterate( tree_t * restrict ptree, int flag )
   easy_value                   =  0;
   easy_abs                     =  0;
   right_answer_made            =  0;
-  is_hash_learn_stored         =  0;
   root_abort                   =  0;
   root_nmove                   =  0;
   root_value                   = -score_bound;
   root_alpha                   = -score_bound;
   root_beta                    =  score_bound;
-  root_move_cap                =  0;
+  root_index                   =  0;
+  root_move_list[0].status     = flag_first;
   node_last_check              =  0;
-  time_last_eff_search         =  time_start;
   time_last_check              =  time_start;
   game_status                 &= ~( flag_move_now | flag_suspend
                                    | flag_quit_ponder | flag_search_error );
@@ -127,6 +154,10 @@ iterate( tree_t * restrict ptree, int flag )
   easy_move                    =  0;
 #endif
 
+#if defined(USI)
+  usi_time_out_last            =  time_start;
+#endif
+
 #if defined(TLP)
   ptree->tlp_abort             = 0;
   tlp_nsplit                   = 0;
@@ -152,6 +183,12 @@ iterate( tree_t * restrict ptree, int flag )
   else { root_mpv = 0; }
 #endif
 
+#if defined(DFPN_CLIENT)
+  dfpn_client_rresult_unlocked = dfpn_client_na;
+  dfpn_client_move_unlocked    = MOVE_NA;
+  dfpn_client_best_move        = MOVE_NA;
+  dfpn_client_cresult_index    = 0;
+#endif
 
   for ( ply = 0; ply < PLY_MAX; ply++ )
     {
@@ -169,12 +206,15 @@ iterate( tree_t * restrict ptree, int flag )
   set_search_limit_time( root_turn );
   adjust_fmg();
 
+  Out( "nsuc_check: [0]=%d [1]=%d\n",
+       (int)ptree->nsuc_check[0], (int)ptree->nsuc_check[1] );
+
   /* look up last pv. */
   if ( last_pv.length )
     {
       Out( "- a pv was found in the previous search result.\n" );
 
-      iteration_depth   = last_pv.depth;
+      iteration_depth   = ( iteration_depth < 1 ) ? 0 : last_pv.depth - 1;
       ptree->pv[0]      = last_pv;
       ptree->pv[0].type = prev_solution;
       root_value        = root_turn ? -last_root_value : last_root_value;
@@ -189,21 +229,18 @@ iterate( tree_t * restrict ptree, int flag )
 #endif
        )
     {
-      unsigned int value_type;
+      unsigned int value_type, dummy;
       int alpha, beta;
     
-      iret = ini_hash();
-      if ( iret < 0 ) { return iret; }
-      is_hash_learn_stored = 1;
-
       value = INT_MIN;
       for ( ply = 1; ply < PLY_MAX - 10; ply++ )
        {
+         dummy = 0;
          alpha = -score_bound;
          beta  =  score_bound;
          
          value_type = hash_probe( ptree, 1, ply*PLY_INC+PLY_INC/2,
-                                  root_turn, alpha, beta, 0 );
+                                  root_turn, alpha, beta, &dummy );
          if ( value_type != value_exact )   { break; }
          value = HASH_VALUE;
       }
@@ -220,9 +257,9 @@ iterate( tree_t * restrict ptree, int flag )
          
          if ( ! ptree->pv[0].length )
            {
-             iteration_depth         = 0;
+             iteration_depth    = 0;
              ptree->pv[0].depth = 0;
-             root_value              = -score_bound;
+             root_value         = -score_bound;
 #if ! defined(MINIMUM)
              out_warning( "PEEK FAILED!!!" );
 #endif
@@ -235,16 +272,21 @@ iterate( tree_t * restrict ptree, int flag )
     unsigned int elapsed;
     
     Out( "- root move generation" );
-    value = make_root_move_list( ptree, flag );
-    if ( game_status & flag_search_error ) { return -1; }
-    if ( game_status & ( flag_quit | flag_quit_ponder | flag_suspend ) )
-      {
-       return 1;
-      }
+    value = make_root_move_list( ptree );
 
     if ( ! root_nmove )
       {
-       str_error = "No legal moves to search";
+#if defined(MNJ_LAN) || defined(USI)
+       if ( moves_ignore[0] != MOVE_NA )
+         {
+           MnjOut( "pid=%d move=%%TORYO v=%de n=0 final%s\n",
+                   mnj_posi_id, -score_bound,
+                   ( mnj_depth_stable == INT_MAX ) ? "" : " stable" );
+
+           return 1;
+         }
+#endif
+       str_error = str_no_legal_move;
        return -2;
       }
 
@@ -256,6 +298,7 @@ iterate( tree_t * restrict ptree, int flag )
        ptree->pv[0].depth  = 1;
        ptree->pv[0].type   = no_rep;
        root_value          = value;
+       root_index          = 0;
       }
 
 #if defined(MPV)
@@ -272,21 +315,72 @@ iterate( tree_t * restrict ptree, int flag )
   }
 
 
+#if defined(DFPN_CLIENT)
+  /* probe results from DFPN searver */
+  dfpn_client_check_results();
+  if ( dfpn_client_move_unlocked != MOVE_NA )
+    {
+      ptree->pv[0].a[1]   = dfpn_client_move_unlocked;
+      ptree->pv[0].length = 1;
+      ptree->pv[0].depth  = 0;
+      ptree->pv[0].type   = no_rep;
+      root_value          = score_matelong;
+    }
+#endif
+
+
   /* save preliminary result */
   assert( root_value != -score_bound );
   last_root_value = root_turn ? -root_value : root_value;
   last_pv         = ptree->pv[0];
 
-#if defined(MNJ_LAN)
-  if ( sckt_mnj != SCKT_NULL )
+
+#if defined(DFPN_CLIENT)
+  /* send the best move to DFPN server */
+  if ( dfpn_client_sckt != SCKT_NULL
+       && dfpn_client_best_move != ptree->pv[0].a[1] )
     {
-      const char *str = ( root_nmove == 1 ) ? "confident" : "";
+      dfpn_client_best_move = ptree->pv[0].a[1];
+      lock( &dfpn_client_lock );
+      dfpn_client_out( "BEST MOVE %s\n", str_CSA_move(dfpn_client_best_move) );
+      unlock( &dfpn_client_lock );
+    }
+#endif
+
+
+#if 0 && defined(MNJ_LAN)
+  /* send the best move to parallel server */
+  if ( sckt_mnj != SCKT_NULL ) {
 
-      MnjOut( "pid=%d move=%s v=%de n=%" PRIu64 " %s\n",
+    if ( moves_ignore[0] == MOVE_NA && root_nmove == 1 ) {
+    /* only one replay */
+      MnjOut( "pid=%d move=%s v=%de n=%" PRIu64 " final%s\n",
              mnj_posi_id, str_CSA_move(ptree->pv[0].a[1]), root_value,
-             ptree->node_searched, str );
+             ptree->node_searched,
+             ( mnj_depth_stable == INT_MAX ) ? "" : " stable" );
+      
+      return 1;
     }
+
+    MnjOut( "pid=%d move=%s v=%de n=%" PRIu64 "\n",
+           mnj_posi_id, str_CSA_move(ptree->pv[0].a[1]), root_value,
+           ptree->node_searched );
+  }
 #endif
+  MnjOut( "pid=%d move=%s v=%de n=%" PRIu64 "\n",
+         mnj_posi_id, str_CSA_move(ptree->pv[0].a[1]), root_value,
+         ptree->node_searched );
+
+#if defined(USI)
+  if ( usi_mode != usi_off )
+    {
+      char str_usi[6];
+      csa2usi( ptree, str_CSA_move(ptree->pv[0].a[1]), str_usi );
+      USIOut( "info depth %d score cp %d nodes %" PRIu64 " pv %s\n",
+             iteration_depth, root_value, ptree->node_searched, str_usi );
+    }
+#endif
+
 
   /* return, if previous pv is long enough */
   if ( abs(root_value) > score_max_eval
@@ -297,11 +391,6 @@ iterate( tree_t * restrict ptree, int flag )
       return 1;
     }
 
-  if ( ! is_hash_learn_stored )
-    {
-      iret = ini_hash();
-      if ( iret < 0 ) { return iret; }
-    }
 
   /* iterative deepening search */
 #if defined(TLP)
@@ -312,15 +401,12 @@ iterate( tree_t * restrict ptree, int flag )
   root_beta        = set_root_beta(  0, root_value );
   root_alpha       = set_root_alpha( 0, root_value );
   root_value       = root_alpha;
-  add_rejections( ptree, root_turn, 1 );
+
   Out( "- drive an iterative deepening search starting from depth %d\n",
        iteration_depth );
 
   for ( ; iteration_depth < 30/*PLY_MAX-10*/; iteration_depth++ ) {
 
-    MnjOut( "pid=%d d=%d\n", mnj_posi_id, iteration_depth );
-
-
     if ( get_elapsed( &time_last_search ) < 0 ) { return -1; }
     
 #if defined(MPV)
@@ -392,12 +478,39 @@ iterate( tree_t * restrict ptree, int flag )
          double dvalue;
          
          root_move_list[0].status &= ~flag_searched;
-         root_move_list[0].status |= flag_failhigh;
          dvalue = (double)( root_turn ? -root_beta : root_beta );
 
          do { root_beta  = set_root_beta( ++root_nfail_high, root_beta ); }
          while ( value >= root_beta );
 
+#if defined(DFPN_CLIENT)
+         if ( dfpn_client_sckt != SCKT_NULL
+              && 4 < iteration_depth
+              && dfpn_client_best_move != ptree->pv[1].a[1] )
+           {
+             dfpn_client_best_move = ptree->pv[1].a[1];
+             lock( &dfpn_client_lock );
+             dfpn_client_out( "BEST MOVE %s\n",
+                              str_CSA_move(dfpn_client_best_move) );
+             unlock( &dfpn_client_lock );
+           }
+#endif
+         MnjOut( "pid=%d move=%s v=%dl n=%" PRIu64 "%s\n",
+                 mnj_posi_id, str_CSA_move(ptree->pv[1].a[1]),
+                 root_beta, ptree->node_searched,
+                 ( mnj_depth_stable <= iteration_depth ) ? " stable" : "" );
+
+#if defined(USI)
+         if ( usi_mode != usi_off )
+           {
+             char str_usi[6];
+             csa2usi( ptree, str_CSA_move(ptree->pv[1].a[1]), str_usi );
+             USIOut( "info depth %d score cp %d nodes %" PRIu64 " pv %s\n",
+                     iteration_depth, root_beta, ptree->node_searched,
+                     str_usi );
+           }
+#endif
+
          str = str_time_symple( time_last_result - time_start );
          if ( root_move_list[0].status & flag_first )
            {
@@ -405,14 +518,8 @@ iterate( tree_t * restrict ptree, int flag )
            }
          else { Out( "    %6s %7.2f ", str, dvalue / 100.0 ); }
 
-         str = str_fail_high( root_turn, root_nfail_high );
-
-         MnjOut( "pid=%d move=%s v=%dl n=%" PRIu64 "\n", mnj_posi_id,
-                 str_CSA_move(ptree->pv[1].a[1]), root_beta,
-                 ptree->node_searched );
-
-         str_move = str_CSA_move_plus( ptree, ptree->pv[1].a[1], 1,
-                                       root_turn );
+         str      = str_fail_high( root_turn, root_nfail_high );
+         str_move = str_CSA_move(ptree->pv[1].a[1]);
          Out( " 1.%c%s [%s!]\n", ach_turn[root_turn], str_move, str );
          
          
@@ -442,7 +549,6 @@ iterate( tree_t * restrict ptree, int flag )
            }
 
          root_move_list[0].status &= ~flag_searched;
-         root_move_list[0].status |= flag_faillow;
          dvalue = (double)( root_turn ? -root_alpha : root_alpha );
 
          if ( get_elapsed( &time_elapsed ) < 0 ) { return -1; }
@@ -454,8 +560,7 @@ iterate( tree_t * restrict ptree, int flag )
          Out( "(%2d)%6s %7.2f ", iteration_depth, str, dvalue / 100.0 );
 
          str      = str_fail_high( Flip(root_turn), root_nfail_low );
-         str_move = str_CSA_move_plus( ptree, root_move_list[0].move, 1,
-                                       root_turn );
+         str_move = str_CSA_move(root_move_list[0].move);
          Out( " 1.%c%s [%s?]\n", ach_turn[root_turn], str_move, str );
          if ( game_status & flag_pondering )
            {
@@ -472,7 +577,7 @@ iterate( tree_t * restrict ptree, int flag )
       else { break; }
     }
 
-    /* the trial of search ended */
+    /* the trial of search is finished */
     if ( root_alpha < root_value && root_value < root_beta )
       {
        last_root_value = root_turn ? - root_value : root_value;
@@ -541,9 +646,7 @@ iterate( tree_t * restrict ptree, int flag )
     }
   }
 
-  /* iteration ended */
-  sub_rejections( ptree, root_turn, 1 );
-
+  /* iteration finished */
   if ( game_status & flag_problem )
     {
       if ( is_answer_right( ptree->pv[0].a[1] ) )
@@ -556,7 +659,7 @@ iterate( tree_t * restrict ptree, int flag )
   {
     int i;
     
-    for ( i = 0; i < HIST_SIZE; i++ )
+    for ( i = 0; i < (int)HIST_SIZE; i++ )
       {
        ptree->hist_good[i]  /= 256U;
        ptree->hist_tried[i] /= 256U;
@@ -564,16 +667,13 @@ iterate( tree_t * restrict ptree, int flag )
   }
   /* prunings and extentions-statistics */
   {
-    double drep, dreject, dhash, dnull, dfh1st;
+    double drep, dhash, dnull, dfh1st;
 
     drep    = (double)ptree->nperpetual_check;
     drep   += (double)ptree->nfour_fold_rep;
     drep   += (double)ptree->nsuperior_rep;
     drep   *= 100.0 / (double)( ptree->nrep_tried + 1 );
 
-    dreject  = 100.0 * (double)ptree->nreject_done;
-    dreject /= (double)( ptree->nreject_tried + 1 );
-
     dhash   = (double)ptree->ntrans_exact;
     dhash  += (double)ptree->ntrans_inferior_hit;
     dhash  += (double)ptree->ntrans_superior_hit;
@@ -587,10 +687,8 @@ iterate( tree_t * restrict ptree, int flag )
     dfh1st  = 100.0 * (double)ptree->fail_high_first;
     dfh1st /= (double)( ptree->fail_high + 1 );
 
-    Out( "    pruning  -> rep=%4.2f%%  reject=%4.2f%%\n", drep, dreject );
-    
-    Out( "    pruning  -> hash=%2.0f%%  null=%2.0f%%  fh1st=%4.1f%%\n",
-        dhash, dnull, dfh1st );
+    Out( "    pruning  -> rep=%4.3f%%  hash=%2.0f%%  null=%2.0f%%"
+        "  fh1st=%4.1f%%\n", drep, dhash, dnull, dfh1st );
     
     Out( "    extension-> chk=%u recap=%u 1rep=%u\n",
         ptree->check_extension_done, ptree->recap_extension_done,
@@ -679,6 +777,60 @@ iterate( tree_t * restrict ptree, int flag )
     }
 #endif
 
+#if defined(DFPN_CLIENT)
+  if ( dfpn_client_sckt != SCKT_NULL )
+    {
+      int asum[4] = { 0, 0, 0, 0 };
+      int i, n;
+
+      n = root_nmove;
+      for ( i = 0; i < n; i += 1 )
+       {
+         asum[ root_move_list[i].dfpn_cresult ] += 1;
+       }
+
+      switch ( dfpn_client_rresult_unlocked )
+       {
+       case dfpn_client_na:
+         Out( "    dfpn     -> n/a " );
+         break;
+
+       case dfpn_client_win:
+         if ( dfpn_client_move_unlocked != MOVE_NA )
+           {
+             Out( "    dfpn     -> win %s ",
+                  str_CSA_move(dfpn_client_move_unlocked) );
+           }
+         else { Out( "    dfpn     -> win ignore " ); }
+         break;
+
+       case dfpn_client_lose:
+         Out( "    dfpn     -> lose " );
+         break;
+
+       default:
+         assert( dfpn_client_misc == dfpn_client_rresult_unlocked );
+         Out( "    dfpn     -> misc " );
+         break;
+       }
+         
+      Out( "(children win %d, lose %d, misc %d, n/a %d)\n",
+          asum[dfpn_client_win], asum[dfpn_client_lose],
+          asum[dfpn_client_misc], asum[dfpn_client_na] );
+    }
+  if ( dfpn_client_move_unlocked )
+    {
+      last_root_value = root_turn ? -score_matelong : score_matelong;
+      last_pv.a[1]   = dfpn_client_move_unlocked;
+      last_pv.length = 1;
+      last_pv.depth  = 0;
+      last_pv.type   = no_rep;
+      MnjOut( "pid=%d move=%s n=0 v=%de final%s\n", mnj_posi_id,
+             str_CSA_move(last_pv.a[1]), score_matelong,
+             ( mnj_depth_stable == INT_MAX ) ? "" : " stable" );
+    }
+#endif
+
   {
     double dcpu_percent, dnps, dmat;
     unsigned int cpu, elapsed;
@@ -709,14 +861,12 @@ iterate( tree_t * restrict ptree, int flag )
     node_per_second  = (unsigned int)( dnps + 0.5 );
 #endif
 
-    dmat             = (double)MATERIAL;
-    dmat            /= (double)MT_CAP_PAWN;
+    dmat  = (double)MATERIAL;
+    dmat /= (double)MT_CAP_PAWN;
 
     OutCsaShogi( " cpu=%.0f nps=%.2f\n", dcpu_percent, dnps / 1e3 );
     Out( "    time=%s  ", str_time_symple( elapsed ) );
-    Out( "cpu=%3.0f%%  mat=%.1f  nps=%.2fK", dcpu_percent, dmat, dnps / 1e3 );
-    Out( "  time_eff=%s\n\n",
-        str_time_symple( time_last_eff_search - time_start ) );
+    Out( "cpu=%3.0f%%  mat=%.1f  nps=%.2fK\n", dcpu_percent, dmat, dnps/1e3 );
   }
 
   if ( ( game_status & flag_problem ) && ! right_answer_made ) { iret = 0; }
@@ -726,29 +876,161 @@ iterate( tree_t * restrict ptree, int flag )
 }
 
 
-static int
-ini_hash( void )
+#if defined(USI)
+int CONV
+usi_root_list( tree_t * restrict ptree )
 {
+#define SIZE_STR ( MAX_LEGAL_MOVES * 6 + 200 )
+  char str[ SIZE_STR ];
+  char str_usi[6];
   unsigned int elapsed;
-  int iret;
+  int i, istr;
 
-  if ( time_limit < 150U ) { return 1; }
-  
-  iret = all_hash_learn_store();
-  if ( iret < 0 ) { return iret; }
-  if ( iret )
+  ptree->node_searched         =  0;
+  ptree->current_move[0]       =  MOVE_NA;
+  ptree->save_eval[0]          =  INT_MAX;
+  ptree->save_eval[1]          =  INT_MAX;
+  ptree->pv[0].a[0]            =  0;
+  ptree->pv[0].a[1]            =  0;
+  ptree->pv[0].depth           =  0;
+  ptree->pv[0].length          =  0;
+  easy_value                   =  0;
+  easy_abs                     =  0;
+  root_abort                   =  0;
+  root_nmove                   =  0;
+  root_value                   = -score_bound;
+  root_alpha                   = -score_bound;
+  root_beta                    =  score_bound;
+  node_last_check              =  0;
+  game_status                 &= ~( flag_move_now | flag_suspend
+                                   | flag_quit_ponder | flag_search_error );
+
+  Out( "- root move generation" );
+  make_root_move_list( ptree );
+
+  if ( game_status & flag_search_error ) { return -1; }
+  if ( game_status & ( flag_quit | flag_quit_ponder | flag_suspend ) )
     {
-      if ( get_elapsed( &elapsed ) < 0 ) { return -1; }
-      Out( "- load learnt hash values (%ss)\n",
-          str_time_symple( elapsed - time_start ) );
+      return 1;
+    }
+
+  if ( ! root_nmove )
+    {
+      str_error = "No legal moves to search";
+      return -1;
+    }
+
+  if ( get_elapsed( &elapsed ) < 0 ) { return -1; }
+  Out( " ... done (%d moves, %ss)\n",
+       root_nmove, str_time_symple( elapsed - time_start ) );
+
+  istr = snprintf( str, SIZE_STR, "genmove_probability" );
+  for ( i = 0; i < root_nmove; i++ )
+    {
+      csa2usi( ptree, str_CSA_move(root_move_list[i].move), str_usi );
+      istr += snprintf( str + istr, SIZE_STR - istr, " %s %d",
+                       str_usi, i + 1 );
+    }
+
+  USIOut( "%s\n", str );
+  return 1;
+}
+
+
+int CONV
+usi_book( tree_t * restrict ptree )
+{
+  char str_usi[6];
+  int is_book_hit;
+
+  if ( pf_book == NULL || rep_book_prob( ptree  ) )
+    {
+      USIOut( "bestmove pass\n" );
+      return 1;
+    }
+
+  is_book_hit = book_probe( ptree );
+  if ( is_book_hit < 0 ) { return is_book_hit; }
+
+  if ( ! is_book_hit )
+    {
+      USIOut( "bestmove pass\n" );
+      return 1;
     }
 
+  csa2usi( ptree, str_CSA_move(ptree->current_move[1]), str_usi );
+  USIOut( "bestmove %s\n", str_usi );
   return 1;
 }
+#endif
+
+
+#if defined(DFPN_CLIENT)
+void CONV
+dfpn_client_check_results( void )
+{
+  int i, n, index, num;
+
+  n = root_nmove;
+  lock( &dfpn_client_lock );
+
+  if ( dfpn_client_rresult_unlocked == dfpn_client_na )
+    {
+      dfpn_client_rresult_unlocked = dfpn_client_rresult;
+      if ( dfpn_client_rresult == dfpn_client_win
+          && dfpn_client_move_unlocked == MOVE_NA )
+       {
+         for ( i = 0; i < n; i += 1 )
+           if ( ! strcmp( (const char *)dfpn_client_str_move,
+                          str_CSA_move(root_move_list[i].move) ) )
+             {
+               dfpn_client_move_unlocked = root_move_list[i].move;
+               break;
+             }
+       }
+    }
+
+  num = dfpn_client_num_cresult;
+  for ( index = dfpn_client_cresult_index; index < num; index += 1 )
+    {
+      for ( i = 0; i < n; i += 1 ) {
+       
+       if ( root_move_list[i].dfpn_cresult != dfpn_client_na ) { continue; }
+       
+       if ( ! strcmp( (const char *)dfpn_client_cresult[index].str_move,
+                      str_CSA_move(root_move_list[i].move) ) ) {
+
+         root_move_list[i].dfpn_cresult
+           = (int)dfpn_client_cresult[index].result;
+         break;
+       }
+      }
+    }
+
+  dfpn_client_cresult_index = index;
+  dfpn_client_flag_read     = 0;
+  unlock( &dfpn_client_lock );
+}
+#endif
+
+
+static int CONV rep_book_prob( tree_t * restrict ptree )
+{
+  int i;
+
+  for ( i = ptree->nrep - 2; i >= 0; i -= 2 )
+    if ( ptree->rep_board_list[i] == HASH_KEY
+        && ptree->rep_hand_list[i] == HAND_B )
+      {
+       Out( "- book is ignored due to a repetition.\n" );
+       return 1;
+      }
+
+  return 0;
+}
 
 
-static void
-adjust_fmg( void )
+static void CONV adjust_fmg( void )
 {
   int misc, cap, drop, mt, misc_king, cap_king;
 
@@ -768,8 +1050,7 @@ adjust_fmg( void )
 }
 
 
-static int
-set_root_beta( int nfail_high, int root_beta_old )
+static int CONV set_root_beta( int nfail_high, int root_beta_old )
 {
   int aspiration_hwdth, aspiration_fail1;
 
@@ -798,8 +1079,7 @@ set_root_beta( int nfail_high, int root_beta_old )
 }
 
 
-static int
-set_root_alpha( int nfail_low, int root_alpha_old )
+static int CONV set_root_alpha( int nfail_low, int root_alpha_old )
 {
   int aspiration_hwdth, aspiration_fail1;
 
@@ -828,8 +1108,7 @@ set_root_alpha( int nfail_low, int root_alpha_old )
 }
 
 
-static const char *
-str_fail_high( int turn, int nfail_high )
+static const char * CONV str_fail_high( int turn, int nfail_high )
 {
   const char *str;
 
@@ -846,8 +1125,7 @@ str_fail_high( int turn, int nfail_high )
 }
 
 
-static int
-is_answer_right( unsigned int move )
+static int CONV is_answer_right( unsigned int move )
 {
   const char *str_anser;
   const char *str_move;