7 static void CONV adjust_fmg( void );
8 static int CONV set_root_alpha( int nfail_low, int root_alpha_old );
9 static int CONV set_root_beta( int nfail_high, int root_beta_old );
10 static int CONV is_answer_right( unsigned int move );
11 static int CONV rep_book_prob( tree_t * restrict ptree );
12 static const char * CONV str_fail_high( int turn, int nfail_high );
16 iterate( tree_t * restrict ptree )
19 unsigned int cpu_start;
20 int right_answer_made;
22 /* probe the opening book */
24 #if defined(USI) || defined(MNJ_LAN)
25 && moves_ignore[0] == MOVE_NA
27 && ! rep_book_prob( ptree ) )
32 is_book_hit = book_probe( ptree );
33 if ( is_book_hit < 0 ) { return is_book_hit; }
35 iret = get_elapsed( &elapsed );
36 if ( iret < 0 ) { return iret; }
38 Out( "- opening book is probed. (%ss)\n",
39 str_time_symple( elapsed - time_start ) );
42 pv_close( ptree, 2, book_hit );
43 last_pv = ptree->pv[1];
45 if ( ! ( game_status & flag_puzzling ) )
47 for ( i = 0; i < (int)HIST_SIZE; i++ )
49 ptree->hist_good[i] /= 256U;
50 ptree->hist_tried[i] /= 256U;
53 MnjOut( "pid=%d move=%s n=0 v=0e final%s\n",
54 mnj_posi_id, str_CSA_move(ptree->pv[1].a[1]),
55 ( mnj_depth_stable == INT_MAX ) ? "" : " stable" );
59 if ( usi_mode != usi_off )
62 csa2usi( ptree, str_CSA_move(ptree->pv[1].a[1]), str_usi );
63 USIOut( "info depth 1 score cp 0 nodes 0 pv %s\n", str_usi );
71 /* detect inaniwa tactics */
72 #if defined(INANIWA_SHIFT)
73 if ( ! inaniwa_flag && 19 < ptree->nrep )
75 if ( root_turn == white
76 && ( BOARD[A7]==-pawn || BOARD[A6]==-pawn || BOARD[A5]==-pawn )
77 && BOARD[B7] == -pawn && BOARD[C7] == -pawn
78 && BOARD[D7] == -pawn && BOARD[E7] == -pawn
79 && BOARD[F7] == -pawn && BOARD[G7] == -pawn
81 && ( BOARD[I7]==-pawn || BOARD[I6]==-pawn || BOARD[I5]==-pawn ) )
83 Out( "\nINANIWA SHIFT TURNED ON (BLACK)\n\n" );
86 if ( ini_trans_table() < 0 ) { return -1; }
89 if ( root_turn == black
90 && ( BOARD[A3]==pawn || BOARD[A4]==pawn || BOARD[A5] == pawn )
91 && BOARD[B3] == pawn && BOARD[C3] == pawn
92 && BOARD[D3] == pawn && BOARD[E3] == pawn
93 && BOARD[F3] == pawn && BOARD[G3] == pawn
95 && ( BOARD[I3]==pawn || BOARD[I4]==pawn || BOARD[I5]==pawn ) )
97 Out( "\nINANIWA SHIFT TURNED ON (WHITE)\n\n" );
100 if ( ini_trans_table() < 0 ) { return -1; }
106 /* initialize variables */
107 if ( get_cputime( &cpu_start ) < 0 ) { return -1; }
109 ptree->node_searched = 0;
110 ptree->null_pruning_done = 0;
111 ptree->null_pruning_tried = 0;
112 ptree->check_extension_done = 0;
113 ptree->recap_extension_done = 0;
114 ptree->onerp_extension_done = 0;
115 ptree->nfour_fold_rep = 0;
116 ptree->nperpetual_check = 0;
117 ptree->nsuperior_rep = 0;
118 ptree->nrep_tried = 0;
119 ptree->neval_called = 0;
120 ptree->nquies_called = 0;
121 ptree->ntrans_always_hit = 0;
122 ptree->ntrans_prefer_hit = 0;
123 ptree->ntrans_probe = 0;
124 ptree->ntrans_exact = 0;
125 ptree->ntrans_lower = 0;
126 ptree->ntrans_upper = 0;
127 ptree->ntrans_superior_hit = 0;
128 ptree->ntrans_inferior_hit = 0;
129 ptree->fail_high = 0;
130 ptree->fail_high_first = 0;
131 ptree->current_move[0] = 0;
132 ptree->save_eval[0] = INT_MAX;
133 ptree->save_eval[1] = INT_MAX;
134 ptree->pv[0].a[0] = 0;
135 ptree->pv[0].a[1] = 0;
136 ptree->pv[0].depth = 0;
137 ptree->pv[0].length = 0;
141 right_answer_made = 0;
144 root_value = -score_bound;
145 root_alpha = -score_bound;
146 root_beta = score_bound;
148 root_move_list[0].status = flag_first;
150 time_last_check = time_start;
151 game_status &= ~( flag_move_now | flag_suspend
152 | flag_quit_ponder | flag_search_error );
153 #if defined(DBG_EASY)
158 usi_time_out_last = time_start;
162 ptree->tlp_abort = 0;
169 if ( ! ( game_status & flag_puzzling ) && mpv_num > 1 )
173 for ( i = 0; i < 2*mpv_num+1; i++ ) { mpv_pv[i].length = 0; }
183 else { root_mpv = 0; }
186 #if defined(DFPN_CLIENT)
187 dfpn_client_rresult_unlocked = dfpn_client_na;
188 dfpn_client_move_unlocked = MOVE_NA;
189 dfpn_client_best_move = MOVE_NA;
190 dfpn_client_cresult_index = 0;
193 for ( ply = 0; ply < PLY_MAX; ply++ )
195 ptree->amove_killer[ply].no1 = ptree->amove_killer[ply].no2 = 0U;
196 ptree->killers[ply].no1 = ptree->killers[ply].no2 = 0x0U;
200 unsigned int u = node_per_second / 16U;
201 if ( u > TIME_CHECK_MAX_NODE ) { u = TIME_CHECK_MAX_NODE; }
202 else if ( u < TIME_CHECK_MIN_NODE ) { u = TIME_CHECK_MIN_NODE; }
203 node_next_signal = u;
206 set_search_limit_time( root_turn );
209 Out( "nsuc_check: [0]=%d [1]=%d\n",
210 (int)ptree->nsuc_check[0], (int)ptree->nsuc_check[1] );
212 /* look up last pv. */
213 if ( last_pv.length && ! analyze_mode )
215 Out( "- a pv was found in the previous search result.\n" );
217 iteration_depth = ( iteration_depth < 1 ) ? 0 : last_pv.depth - 1;
218 ptree->pv[0] = last_pv;
219 ptree->pv[0].type = prev_solution;
220 root_value = root_turn ? -last_root_value : last_root_value;
221 out_pv( ptree, root_value, root_turn, 0 );
225 /* probe the transposition table, since last pv is not available. */
226 if ( ! last_pv.length && ! analyze_mode
232 unsigned int value_type, dummy;
236 for ( ply = 1; ply < PLY_MAX - 10; ply++ )
239 alpha = -score_bound;
242 value_type = hash_probe( ptree, 1, ply*PLY_INC+PLY_INC/2,
243 root_turn, alpha, beta, &dummy );
244 if ( value_type != value_exact ) { break; }
248 if ( -score_bound < value )
250 Out( "- a pv was peeked through the transposition table.\n" );
251 iteration_depth = ply-1;
252 ptree->pv[0].depth = (unsigned char)(ply-1);
253 ptree->pv[0].type = hash_hit;
255 out_pv( ptree, value, root_turn, 0 );
258 if ( ! ptree->pv[0].length )
261 ptree->pv[0].depth = 0;
262 root_value = -score_bound;
263 #if ! defined(MINIMUM)
264 out_warning( "PEEK FAILED!!!" );
270 /* root move generation */
272 unsigned int elapsed;
274 Out( "- root move generation" );
275 value = make_root_move_list( ptree );
279 #if defined(MNJ_LAN) || defined(USI)
280 if ( moves_ignore[0] != MOVE_NA )
282 MnjOut( "pid=%d move=%%TORYO v=%de n=0 final%s\n",
283 mnj_posi_id, -score_bound,
284 ( mnj_depth_stable == INT_MAX ) ? "" : " stable" );
289 str_error = str_no_legal_move;
293 if ( ! ptree->pv[0].length || ptree->pv[0].a[1] != root_move_list[0].move )
296 ptree->pv[0].a[1] = root_move_list[0].move;
297 ptree->pv[0].length = 1;
298 ptree->pv[0].depth = 1;
299 ptree->pv[0].type = no_rep;
307 if ( root_nmove == 1 ) { root_mpv = 0; }
312 if ( get_elapsed( &elapsed ) < 0 ) { return -1; }
313 Out( " ... done (%d moves, %ss)\n",
314 root_nmove, str_time_symple( elapsed - time_start ) );
318 #if defined(DFPN_CLIENT)
319 /* probe results from DFPN searver */
320 dfpn_client_check_results();
321 if ( dfpn_client_move_unlocked != MOVE_NA )
323 ptree->pv[0].a[1] = dfpn_client_move_unlocked;
324 ptree->pv[0].length = 1;
325 ptree->pv[0].depth = 0;
326 ptree->pv[0].type = no_rep;
327 root_value = score_matelong;
332 /* save preliminary result */
333 assert( root_value != -score_bound );
334 last_root_value = root_turn ? -root_value : root_value;
335 last_pv = ptree->pv[0];
338 #if defined(DFPN_CLIENT)
339 /* send the best move to DFPN server */
340 if ( dfpn_client_sckt != SCKT_NULL
341 && dfpn_client_best_move != ptree->pv[0].a[1] )
343 dfpn_client_best_move = ptree->pv[0].a[1];
344 lock( &dfpn_client_lock );
345 dfpn_client_out( "BEST MOVE %s\n", str_CSA_move(dfpn_client_best_move) );
346 unlock( &dfpn_client_lock );
351 #if 0 && defined(MNJ_LAN)
352 /* send the best move to parallel server */
353 if ( sckt_mnj != SCKT_NULL ) {
355 if ( moves_ignore[0] == MOVE_NA && root_nmove == 1 ) {
356 /* only one replay */
357 MnjOut( "pid=%d move=%s v=%de n=%" PRIu64 " final%s\n",
358 mnj_posi_id, str_CSA_move(ptree->pv[0].a[1]), root_value,
359 ptree->node_searched,
360 ( mnj_depth_stable == INT_MAX ) ? "" : " stable" );
365 MnjOut( "pid=%d move=%s v=%de n=%" PRIu64 "\n",
366 mnj_posi_id, str_CSA_move(ptree->pv[0].a[1]), root_value,
367 ptree->node_searched );
370 MnjOut( "pid=%d move=%s v=%de n=%" PRIu64 "\n",
371 mnj_posi_id, str_CSA_move(ptree->pv[0].a[1]), root_value,
372 ptree->node_searched );
375 if ( usi_mode != usi_off )
378 csa2usi( ptree, str_CSA_move(ptree->pv[0].a[1]), str_usi );
379 USIOut( "info depth %d score cp %d nodes %" PRIu64 " pv %s\n",
380 iteration_depth, root_value, ptree->node_searched, str_usi );
385 /* return, if previous pv is long enough */
386 if ( abs(root_value) > score_max_eval
387 || iteration_depth >= depth_limit
388 || ( ( game_status & flag_puzzling )
389 && ( root_nmove == 1 || ptree->pv[0].depth > 4 ) ) )
395 /* iterative deepening search */
398 if ( iret < 0 ) { return iret; }
400 iteration_depth += 1;
401 root_beta = set_root_beta( 0, root_value );
402 root_alpha = set_root_alpha( 0, root_value );
403 root_value = root_alpha;
405 Out( "- drive an iterative deepening search starting from depth %d\n",
408 for ( ; iteration_depth < 30/*PLY_MAX-10*/; iteration_depth++ ) {
410 if ( get_elapsed( &time_last_search ) < 0 ) { return -1; }
416 i = ( root_nmove < mpv_num ) ? root_nmove : mpv_num;
417 for ( ; i < mpv_num*2; i++ ) { mpv_pv[i].length = 0; }
426 for ( ply = 1; ply <= ptree->pv[0].length; ply++ )
428 move = ptree->pv[0].a[ply];
429 if ( ! is_move_valid( ptree, move, tt ) )
431 #if ! defined(MINIMUM)
432 out_warning( "Old pv has an illegal move! ply=%d, move=%s",
433 ply, str_CSA_move(move) );
437 MakeMove( tt, move, ply );
440 #if ! defined(MINIMUM)
441 out_warning( "Old pv has an illegal evasion! ply=%d, move=%s",
442 ply, str_CSA_move(move) );
444 UnMakeMove( tt, move, ply );
449 for ( ply--; ply > 0; ply-- )
452 move = ptree->pv[0].a[ply];
453 UnMakeMove( tt, move, ply );
454 hash_store_pv( ptree, move, tt );
461 root_move_list[0].status = flag_first;
462 for ( i = 1; i < n; i++ ) { root_move_list[i].status = 0; }
465 /* a trial of searches */
467 value = searchr( ptree, root_alpha, root_beta, root_turn,
468 iteration_depth*PLY_INC + PLY_INC/2 );
469 if ( game_status & flag_search_error ) { return -1; }
470 if ( root_abort ) { break; }
472 assert( abs(value) < score_foul );
474 if ( root_beta <= value )
476 const char *str_move;
480 root_move_list[0].status &= ~flag_searched;
481 dvalue = (double)( root_turn ? -root_beta : root_beta );
483 do { root_beta = set_root_beta( ++root_nfail_high, root_beta ); }
484 while ( value >= root_beta );
486 #if defined(DFPN_CLIENT)
487 if ( dfpn_client_sckt != SCKT_NULL
488 && 4 < iteration_depth
489 && dfpn_client_best_move != ptree->pv[1].a[1] )
491 dfpn_client_best_move = ptree->pv[1].a[1];
492 lock( &dfpn_client_lock );
493 dfpn_client_out( "BEST MOVE %s\n",
494 str_CSA_move(dfpn_client_best_move) );
495 unlock( &dfpn_client_lock );
498 MnjOut( "pid=%d move=%s v=%dl n=%" PRIu64 "%s\n",
499 mnj_posi_id, str_CSA_move(ptree->pv[1].a[1]),
500 root_beta, ptree->node_searched,
501 ( mnj_depth_stable <= iteration_depth ) ? " stable" : "" );
504 if ( usi_mode != usi_off )
507 csa2usi( ptree, str_CSA_move(ptree->pv[1].a[1]), str_usi );
508 USIOut( "info depth %d score cp %d nodes %" PRIu64 " pv %s\n",
509 iteration_depth, root_beta, ptree->node_searched,
514 str = str_time_symple( time_last_result - time_start );
515 if ( root_move_list[0].status & flag_first )
517 Out( "(%2d)%6s %7.2f ", iteration_depth, str, dvalue / 100.0 );
519 else { Out( " %6s %7.2f ", str, dvalue / 100.0 ); }
521 str = str_fail_high( root_turn, root_nfail_high );
522 str_move = str_CSA_move(ptree->pv[1].a[1]);
523 Out( " 1.%c%s [%s!]\n", ach_turn[root_turn], str_move, str );
526 if ( game_status & flag_pondering )
528 OutCsaShogi( "info%+.2f %c%s %c%s [%s!]\n",
529 dvalue / 100.0, ach_turn[Flip(root_turn)],
530 str_CSA_move(ponder_move),
531 ach_turn[root_turn], str_move, str );
534 OutCsaShogi( "info%+.2f %c%s [%s!]\n", dvalue / 100.0,
535 ach_turn[root_turn], str_move, str );
538 else if ( value <= root_alpha )
540 const char *str_move;
542 unsigned int time_elapsed;
545 if ( ! ( root_move_list[0].status & flag_first ) )
547 root_value = root_alpha;
551 root_move_list[0].status &= ~flag_searched;
552 dvalue = (double)( root_turn ? -root_alpha : root_alpha );
554 if ( get_elapsed( &time_elapsed ) < 0 ) { return -1; }
556 do { root_alpha = set_root_alpha( ++root_nfail_low, root_alpha ); }
557 while ( value <= root_alpha );
558 root_value = root_alpha;
559 str = str_time_symple( time_elapsed - time_start );
560 Out( "(%2d)%6s %7.2f ", iteration_depth, str, dvalue / 100.0 );
562 str = str_fail_high( Flip(root_turn), root_nfail_low );
563 str_move = str_CSA_move(root_move_list[0].move);
564 Out( " 1.%c%s [%s?]\n", ach_turn[root_turn], str_move, str );
565 if ( game_status & flag_pondering )
567 OutCsaShogi( "info%+.2f %c%s %c%s [%s?]\n",
568 dvalue / 100.0, ach_turn[Flip(root_turn)],
569 str_CSA_move(ponder_move),
570 ach_turn[root_turn], str_move, str );
573 OutCsaShogi( "info%+.2f %c%s [%s?]\n", dvalue / 100.0,
574 ach_turn[root_turn], str_move, str );
580 /* the trial of search is finished */
581 if ( root_alpha < root_value && root_value < root_beta )
583 last_root_value = root_turn ? - root_value : root_value;
584 last_pv = ptree->pv[0];
587 if ( root_abort ) { break; }
589 if ( root_alpha < root_value && root_value < root_beta )
591 #if ! defined(MINIMUM)
595 for ( i = 0; i < n; i++ )
597 if ( root_move_list[i].status & flag_searched ) { continue; }
598 out_warning( "A root move %s is ignored\n",
599 str_CSA_move(root_move_list[i].move) );
604 if ( ( game_status & flag_problem ) && depth_limit == PLY_MAX )
606 if ( is_answer_right( ptree->pv[0].a[1] ) )
608 if ( right_answer_made > 1 && iteration_depth > 3 ) { break; }
611 else { right_answer_made = 0; }
614 if ( abs(value) > score_max_eval ) { break; }
615 if ( iteration_depth >= depth_limit ) { break; }
617 root_beta = set_root_beta( 0, value );
618 root_alpha = set_root_alpha( 0, value );
619 root_value = root_alpha;
621 #if ! defined(MINIMUM)
622 else { out_warning(( "SEARCH INSTABILITY IS DETECTED!!!" )); }
627 root_move_t root_move_swap;
628 const int n = root_nmove;
632 for ( k = SHELL_H_LEN - 1; k >= 0; k-- )
635 for ( i = n-h-1; i > 0; i-- )
637 root_move_swap = root_move_list[i];
638 sortv = root_move_list[i].nodes;
639 for ( j = i+h; j < n && root_move_list[j].nodes > sortv; j += h )
641 root_move_list[j-h] = root_move_list[j];
643 root_move_list[j-h] = root_move_swap;
649 /* iteration finished */
650 if ( game_status & flag_problem )
652 if ( is_answer_right( ptree->pv[0].a[1] ) )
654 right_answer_made = 1;
656 else { right_answer_made = 0; }
662 for ( i = 0; i < (int)HIST_SIZE; i++ )
664 ptree->hist_good[i] /= 256U;
665 ptree->hist_tried[i] /= 256U;
668 /* prunings and extentions-statistics */
670 double drep, dhash, dnull, dfh1st;
672 drep = (double)ptree->nperpetual_check;
673 drep += (double)ptree->nfour_fold_rep;
674 drep += (double)ptree->nsuperior_rep;
675 drep *= 100.0 / (double)( ptree->nrep_tried + 1 );
677 dhash = (double)ptree->ntrans_exact;
678 dhash += (double)ptree->ntrans_inferior_hit;
679 dhash += (double)ptree->ntrans_superior_hit;
680 dhash += (double)ptree->ntrans_upper;
681 dhash += (double)ptree->ntrans_lower;
682 dhash *= 100.0 / (double)( ptree->ntrans_probe + 1 );
684 dnull = 100.0 * (double)ptree->null_pruning_done;
685 dnull /= (double)( ptree->null_pruning_tried + 1 );
687 dfh1st = 100.0 * (double)ptree->fail_high_first;
688 dfh1st /= (double)( ptree->fail_high + 1 );
690 Out( " pruning -> rep=%4.3f%% hash=%2.0f%% null=%2.0f%%"
691 " fh1st=%4.1f%%\n", drep, dhash, dnull, dfh1st );
693 Out( " extension-> chk=%u recap=%u 1rep=%u\n",
694 ptree->check_extension_done, ptree->recap_extension_done,
695 ptree->onerp_extension_done );
698 /* futility threashold */
699 #if ! ( defined(NO_STDOUT) && defined(NO_LOGGING) )
705 int misc_k = fmg_misc_king;
706 int cap_k = fmg_cap_king;
707 Out( " futility -> misc=%d drop=%d cap=%d mt=%d misc(k)=%d cap(k)=%d\n",
708 misc, drop, cap, mt, misc_k, cap_k );
712 /* hashing-statistics */
714 double dalways, dprefer, dsupe, dinfe;
715 double dlower, dupper, dsat;
717 int ntrans_table, i, n;
719 ntrans_table = 1 << log2_ntrans_table;
720 if ( ntrans_table > 8192 ) { ntrans_table = 8192; }
722 for ( i = 0, n = 0; i < ntrans_table; i++ )
724 word2 = ptrans_table[i].prefer.word2;
725 SignKey( word2, ptrans_table[i].prefer.word1 );
726 if ( trans_table_age == ( 7 & (int)word2 ) ) { n++; }
728 word2 = ptrans_table[i].always[0].word2;
729 SignKey( word2, ptrans_table[i].always[0].word1 );
730 if ( trans_table_age == ( 7 & (int)word2 ) ) { n++; }
732 word2 = ptrans_table[i].always[1].word2;
733 SignKey( word2, ptrans_table[i].always[1].word1 );
734 if ( trans_table_age == ( 7 & (int)word2 ) ) { n++; }
737 dalways = 100.0 * (double)ptree->ntrans_always_hit;
738 dalways /= (double)( ptree->ntrans_probe + 1 );
740 dprefer = 100.0 * (double)ptree->ntrans_prefer_hit;
741 dprefer /= (double)( ptree->ntrans_probe + 1 );
743 dsupe = 100.0 * (double)ptree->ntrans_superior_hit;
744 dsupe /= (double)( ptree->ntrans_probe + 1 );
746 dinfe = 100.0 * (double)ptree->ntrans_inferior_hit;
747 dinfe /= (double)( ptree->ntrans_probe + 1 );
749 Out( " hashing -> always=%2.0f%% prefer=%2.0f%% supe=%4.2f%% "
750 "infe=%4.2f%%\n", dalways, dprefer, dsupe, dinfe );
752 dlower = 100.0 * (double)ptree->ntrans_lower;
753 dlower /= (double)( ptree->ntrans_probe + 1 );
755 dupper = 100.0 * (double)ptree->ntrans_upper;
756 dupper /= (double)( ptree->ntrans_probe + 1 );
758 dsat = 100.0 * (double)n;
759 dsat /= (double)( 3 * ntrans_table );
761 OutCsaShogi( "statsatu=%.0f", dsat );
763 "exact=%d lower=%2.0f%% upper=%4.2f%% sat=%2.0f%% age=%d\n",
764 ptree->ntrans_exact, dlower, dupper, dsat, trans_table_age );
765 if ( dsat > 9.0 ) { trans_table_age = ( trans_table_age + 1 ) & 0x7; }
771 Out( " threading-> split=%d abort=%d slot=%d\n",
772 tlp_nsplit, tlp_nabort, tlp_nslot+1 );
773 if ( tlp_nslot+1 == TLP_NUM_WORK )
775 out_warning( "THREAD WORK AREA IS USED UP!!!" );
780 #if defined(DFPN_CLIENT)
781 if ( dfpn_client_sckt != SCKT_NULL )
783 int asum[4] = { 0, 0, 0, 0 };
787 for ( i = 0; i < n; i += 1 )
789 asum[ root_move_list[i].dfpn_cresult ] += 1;
792 switch ( dfpn_client_rresult_unlocked )
795 Out( " dfpn -> n/a " );
798 case dfpn_client_win:
799 if ( dfpn_client_move_unlocked != MOVE_NA )
801 Out( " dfpn -> win %s ",
802 str_CSA_move(dfpn_client_move_unlocked) );
804 else { Out( " dfpn -> win ignore " ); }
807 case dfpn_client_lose:
808 Out( " dfpn -> lose " );
812 assert( dfpn_client_misc == dfpn_client_rresult_unlocked );
813 Out( " dfpn -> misc " );
817 Out( "(children win %d, lose %d, misc %d, n/a %d)\n",
818 asum[dfpn_client_win], asum[dfpn_client_lose],
819 asum[dfpn_client_misc], asum[dfpn_client_na] );
821 if ( dfpn_client_move_unlocked )
823 last_root_value = root_turn ? -score_matelong : score_matelong;
824 last_pv.a[1] = dfpn_client_move_unlocked;
827 last_pv.type = no_rep;
828 MnjOut( "pid=%d move=%s n=0 v=%de final%s\n", mnj_posi_id,
829 str_CSA_move(last_pv.a[1]), score_matelong,
830 ( mnj_depth_stable == INT_MAX ) ? "" : " stable" );
835 double dcpu_percent, dnps, dmat;
836 unsigned int cpu, elapsed;
838 Out( " n=%" PRIu64 " quies=%u eval=%u rep=%u %u(chk) %u(supe)\n",
839 ptree->node_searched, ptree->nquies_called, ptree->neval_called,
840 ptree->nfour_fold_rep, ptree->nperpetual_check,
841 ptree->nsuperior_rep );
843 if ( get_cputime( &cpu ) < 0 ) { return -1; }
844 if ( get_elapsed( &elapsed ) < 0 ) { return -1; }
847 elapsed -= time_start;
849 dcpu_percent = 100.0 * (double)cpu;
850 dcpu_percent /= (double)( elapsed + 1U );
852 dnps = 1000.0 * (double)ptree->node_searched;
853 dnps /= (double)( elapsed + 1U );
857 double n = (double)tlp_max;
858 node_per_second = (unsigned int)( ( dnps + 0.5 ) / n );
861 node_per_second = (unsigned int)( dnps + 0.5 );
864 dmat = (double)MATERIAL;
865 dmat /= (double)MT_CAP_PAWN;
867 OutCsaShogi( " cpu=%.0f nps=%.2f\n", dcpu_percent, dnps / 1e3 );
868 Out( " time=%s ", str_time_symple( elapsed ) );
869 Out( "cpu=%3.0f%% mat=%.1f nps=%.2fK\n", dcpu_percent, dmat, dnps/1e3 );
872 if ( ( game_status & flag_problem ) && ! right_answer_made ) { iret = 0; }
881 usi_root_list( tree_t * restrict ptree )
883 #define SIZE_STR ( MAX_LEGAL_MOVES * 6 + 200 )
884 char str[ SIZE_STR ];
886 unsigned int elapsed;
889 ptree->node_searched = 0;
890 ptree->current_move[0] = MOVE_NA;
891 ptree->save_eval[0] = INT_MAX;
892 ptree->save_eval[1] = INT_MAX;
893 ptree->pv[0].a[0] = 0;
894 ptree->pv[0].a[1] = 0;
895 ptree->pv[0].depth = 0;
896 ptree->pv[0].length = 0;
901 root_value = -score_bound;
902 root_alpha = -score_bound;
903 root_beta = score_bound;
905 game_status &= ~( flag_move_now | flag_suspend
906 | flag_quit_ponder | flag_search_error );
908 Out( "- root move generation" );
909 make_root_move_list( ptree );
911 if ( game_status & flag_search_error ) { return -1; }
912 if ( game_status & ( flag_quit | flag_quit_ponder | flag_suspend ) )
919 str_error = "No legal moves to search";
923 if ( get_elapsed( &elapsed ) < 0 ) { return -1; }
924 Out( " ... done (%d moves, %ss)\n",
925 root_nmove, str_time_symple( elapsed - time_start ) );
927 istr = snprintf( str, SIZE_STR, "genmove_probability" );
928 for ( i = 0; i < root_nmove; i++ )
930 csa2usi( ptree, str_CSA_move(root_move_list[i].move), str_usi );
931 istr += snprintf( str + istr, SIZE_STR - istr, " %s %d",
935 USIOut( "%s\n", str );
941 usi_book( tree_t * restrict ptree )
946 if ( pf_book == NULL || rep_book_prob( ptree ) )
948 USIOut( "bestmove pass\n" );
952 is_book_hit = book_probe( ptree );
953 if ( is_book_hit < 0 ) { return is_book_hit; }
957 USIOut( "bestmove pass\n" );
961 csa2usi( ptree, str_CSA_move(ptree->current_move[1]), str_usi );
962 USIOut( "bestmove %s\n", str_usi );
968 #if defined(DFPN_CLIENT)
970 dfpn_client_check_results( void )
972 int i, n, index, num;
975 lock( &dfpn_client_lock );
977 if ( dfpn_client_rresult_unlocked == dfpn_client_na )
979 dfpn_client_rresult_unlocked = dfpn_client_rresult;
980 if ( dfpn_client_rresult == dfpn_client_win
981 && dfpn_client_move_unlocked == MOVE_NA )
983 for ( i = 0; i < n; i += 1 )
984 if ( ! strcmp( (const char *)dfpn_client_str_move,
985 str_CSA_move(root_move_list[i].move) ) )
987 dfpn_client_move_unlocked = root_move_list[i].move;
993 num = dfpn_client_num_cresult;
994 for ( index = dfpn_client_cresult_index; index < num; index += 1 )
996 for ( i = 0; i < n; i += 1 ) {
998 if ( root_move_list[i].dfpn_cresult != dfpn_client_na ) { continue; }
1000 if ( ! strcmp( (const char *)dfpn_client_cresult[index].str_move,
1001 str_CSA_move(root_move_list[i].move) ) ) {
1003 root_move_list[i].dfpn_cresult
1004 = (int)dfpn_client_cresult[index].result;
1010 dfpn_client_cresult_index = index;
1011 dfpn_client_flag_read = 0;
1012 unlock( &dfpn_client_lock );
1017 static int CONV rep_book_prob( tree_t * restrict ptree )
1021 for ( i = ptree->nrep - 2; i >= 0; i -= 2 )
1022 if ( ptree->rep_board_list[i] == HASH_KEY
1023 && ptree->rep_hand_list[i] == HAND_B )
1025 Out( "- book is ignored due to a repetition.\n" );
1033 static void CONV adjust_fmg( void )
1035 int misc, cap, drop, mt, misc_king, cap_king;
1037 misc = fmg_misc - FMG_MG / 2;
1038 cap = fmg_cap - FMG_MG / 2;
1039 drop = fmg_drop - FMG_MG / 2;
1040 misc_king = fmg_misc_king - FMG_MG_KING / 2;
1041 cap_king = fmg_cap_king - FMG_MG_KING / 2;
1042 mt = fmg_mt - FMG_MG_MT / 2;
1044 fmg_misc = ( misc < FMG_MISC ) ? FMG_MISC : misc;
1045 fmg_cap = ( cap < FMG_CAP ) ? FMG_CAP : cap;
1046 fmg_drop = ( drop < FMG_DROP ) ? FMG_DROP : drop;
1047 fmg_misc_king = ( misc_king < FMG_MISC_KING ) ? FMG_MISC_KING : misc_king;
1048 fmg_cap_king = ( cap_king < FMG_CAP_KING ) ? FMG_CAP_KING : cap_king;
1049 fmg_mt = ( mt < FMG_MT ) ? FMG_MT : mt;
1053 static int CONV set_root_beta( int nfail_high, int root_beta_old )
1055 int aspiration_hwdth, aspiration_fail1;
1057 if ( time_max_limit != time_limit )
1059 aspiration_hwdth = MT_CAP_DRAGON / 8;
1060 aspiration_fail1 = MT_CAP_DRAGON / 2;
1063 aspiration_hwdth = MT_CAP_DRAGON / 4;
1064 aspiration_fail1 = ( MT_CAP_DRAGON * 3 ) / 4;
1067 switch ( nfail_high )
1069 case 0: root_beta_old += aspiration_hwdth; break;
1070 case 1: root_beta_old += aspiration_fail1 - aspiration_hwdth; break;
1071 case 2: root_beta_old = score_bound; break;
1073 out_error( "Error at set_root_beta!" );
1076 if ( root_beta_old > score_max_eval ) { root_beta_old = score_bound; }
1078 return root_beta_old;
1082 static int CONV set_root_alpha( int nfail_low, int root_alpha_old )
1084 int aspiration_hwdth, aspiration_fail1;
1086 if ( time_max_limit != time_limit )
1088 aspiration_hwdth = MT_CAP_DRAGON / 8;
1089 aspiration_fail1 = MT_CAP_DRAGON / 2;
1092 aspiration_hwdth = MT_CAP_DRAGON / 4;
1093 aspiration_fail1 = ( MT_CAP_DRAGON * 3 ) / 4;
1096 switch ( nfail_low )
1098 case 0: root_alpha_old -= aspiration_hwdth; break;
1099 case 1: root_alpha_old -= aspiration_fail1 - aspiration_hwdth; break;
1100 case 2: root_alpha_old = -score_bound; break;
1102 out_error( "Error at set_root_alpha!" );
1105 if ( root_alpha_old < -score_max_eval ) { root_alpha_old = -score_bound; }
1107 return root_alpha_old;
1111 static const char * CONV str_fail_high( int turn, int nfail_high )
1115 if ( time_max_limit != time_limit )
1117 if ( nfail_high == 1 ) { str = turn ? "-1" : "+1"; }
1118 else { str = turn ? "-4" : "+4"; }
1121 if ( nfail_high == 1 ) { str = turn ? "-2" : "+2"; }
1122 else { str = turn ? "-6" : "+6"; }
1128 static int CONV is_answer_right( unsigned int move )
1130 const char *str_anser;
1131 const char *str_move;
1135 str_move = str_CSA_move( move );
1137 for ( ianser = 0; ianser < MAX_ANSWER; ianser++ )
1139 str_anser = &( record_problems.info.str_move[ianser][0] );
1140 if ( str_anser[0] == '\0' ) { break; }
1141 if ( ! strcmp( str_anser+1, str_move ) )