Force iteration to start at 1 in analyze mode
[bonanza.git] / iterate.c
1 #include <assert.h>
2 #include <limits.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include "shogi.h"
6
7 static void adjust_fmg( void );
8 static int ini_hash( void );
9 static int set_root_alpha( int nfail_low, int root_alpha_old );
10 static int set_root_beta( int nfail_high, int root_beta_old );
11 static int is_answer_right( unsigned int move );
12 static const char *str_fail_high( int turn, int nfail_high );
13
14
15 static int rep_book_prob( tree_t * restrict ptree )
16 {
17   int i;
18
19   for ( i = root_nrep - 2; i >= 0; i -= 2 )
20     if ( ptree->rep_board_list[i] == HASH_KEY
21          && ptree->rep_hand_list[i] == HAND_B )
22       {
23         Out( "- book is ignored due to a repetition.\n" );
24         return 1;
25       }
26
27   return 0;
28 }
29
30
31 int
32 iterate( tree_t * restrict ptree, int flag )
33 {
34   int value, iret, ply, is_hash_learn_stored;
35   unsigned int cpu_start;
36   int right_answer_made;
37
38   /* probe the opening book */
39   if ( pf_book != NULL && n_nobook_move < 7 && ! rep_book_prob( ptree  ) )
40     {
41       int is_book_hit, i;
42       unsigned int elapsed;
43
44       is_book_hit = book_probe( ptree );
45       if ( is_book_hit < 0 ) { return is_book_hit; }
46
47       iret = get_elapsed( &elapsed );
48       if ( iret < 0 ) { return iret; }
49
50       Out( "- opening book is probed. (%ss)\n",
51            str_time_symple( elapsed - time_start ) );
52       if ( is_book_hit )
53         {
54           pv_close( ptree, 2, book_hit );
55           last_pv         = ptree->pv[1];
56           last_root_value = 0;
57           n_nobook_move   = 0;
58           if ( ! ( game_status & flag_puzzling ) )
59             {
60               for ( i = 0; i < HIST_SIZE; i++ )
61                 {
62                   ptree->hist_good[i]  /= 256U;
63                   ptree->hist_tried[i] /= 256U;
64                 }
65             }
66
67           MnjOut( "pid=%d move=%s v=0b n=0 confident\n", mnj_posi_id,
68                   str_CSA_move(ptree->pv[1].a[1]) );
69
70           return 1;
71         }
72       if ( ! ( game_status & ( flag_puzzling | flag_pondering ) ) )
73         {
74           n_nobook_move += 1;
75         }
76     }
77
78   /* initialize variables */
79   if ( get_cputime( &cpu_start ) < 0 ) { return -1; }
80
81   ptree->node_searched         =  0;
82   ptree->nreject_done          =  0;
83   ptree->nreject_tried         =  0;
84   ptree->null_pruning_done     =  0;
85   ptree->null_pruning_tried    =  0;
86   ptree->check_extension_done  =  0;
87   ptree->recap_extension_done  =  0;
88   ptree->onerp_extension_done  =  0;
89   ptree->nfour_fold_rep        =  0;
90   ptree->nperpetual_check      =  0;
91   ptree->nsuperior_rep         =  0;
92   ptree->nrep_tried            =  0;
93   ptree->neval_called          =  0;
94   ptree->nquies_called         =  0;
95   ptree->ntrans_always_hit     =  0;
96   ptree->ntrans_prefer_hit     =  0;
97   ptree->ntrans_probe          =  0;
98   ptree->ntrans_exact          =  0;
99   ptree->ntrans_lower          =  0;
100   ptree->ntrans_upper          =  0;
101   ptree->ntrans_superior_hit   =  0;
102   ptree->ntrans_inferior_hit   =  0;
103   ptree->fail_high             =  0;
104   ptree->fail_high_first       =  0;
105   ptree->current_move[0]       =  0;
106   ptree->pv[0].a[0]            =  0;
107   ptree->pv[0].a[1]            =  0;
108   ptree->pv[0].depth           =  0;
109   ptree->pv[0].length          =  0;
110   iteration_depth              =  0;
111   easy_value                   =  0;
112   easy_abs                     =  0;
113   right_answer_made            =  0;
114   is_hash_learn_stored         =  0;
115   root_abort                   =  0;
116   root_nmove                   =  0;
117   root_value                   = -score_bound;
118   root_alpha                   = -score_bound;
119   root_beta                    =  score_bound;
120   root_move_cap                =  0;
121   node_last_check              =  0;
122   time_last_eff_search         =  time_start;
123   time_last_check              =  time_start;
124   game_status                 &= ~( flag_move_now | flag_suspend
125                                     | flag_quit_ponder | flag_search_error );
126 #if defined(DBG_EASY)
127   easy_move                    =  0;
128 #endif
129
130 #if defined(TLP)
131   ptree->tlp_abort             = 0;
132   tlp_nsplit                   = 0;
133   tlp_nabort                   = 0;
134   tlp_nslot                    = 0;
135 #endif
136
137 #if defined(MPV)
138   if ( ! ( game_status & flag_puzzling ) && mpv_num > 1 )
139     {
140       int i;
141
142       for ( i = 0; i < 2*mpv_num+1; i++ ) { mpv_pv[i].length = 0; }
143       
144       last_pv.a[0]    = 0;
145       last_pv.a[1]    = 0;
146       last_pv.depth   = 0;
147       last_pv.length  = 0;
148       last_root_value = 0;
149
150       root_mpv = 1;
151     }
152   else { root_mpv = 0; }
153 #endif
154
155
156   for ( ply = 0; ply < PLY_MAX; ply++ )
157     {
158       ptree->amove_killer[ply].no1 = ptree->amove_killer[ply].no2 = 0U;
159       ptree->killers[ply].no1 = ptree->killers[ply].no2 = 0x0U;
160     }
161
162   {
163     unsigned int u =  node_per_second / 16U;
164     if      ( u > TIME_CHECK_MAX_NODE ) { u = TIME_CHECK_MAX_NODE; }
165     else if ( u < TIME_CHECK_MIN_NODE ) { u = TIME_CHECK_MIN_NODE; }
166     node_next_signal = u;
167   }
168
169   set_search_limit_time( root_turn );
170   adjust_fmg();
171
172   /* look up last pv. */
173   if ( last_pv.length && ! analyze_mode )
174     {
175       Out( "- a pv was found in the previous search result.\n" );
176
177       iteration_depth   = last_pv.depth;
178       ptree->pv[0]      = last_pv;
179       ptree->pv[0].type = prev_solution;
180       root_value        = root_turn ? -last_root_value : last_root_value;
181       out_pv( ptree, root_value, root_turn, 0 );
182       Out( "\n" );
183     }
184
185   /* probe the transposition table, since last pv is not available.  */
186   if ( ! last_pv.length && ! analyze_mode
187 #if defined(MPV)
188        && ! root_mpv
189 #endif
190        )
191     {
192       unsigned int value_type;
193       int alpha, beta;
194     
195       iret = ini_hash();
196       if ( iret < 0 ) { return iret; }
197       is_hash_learn_stored = 1;
198
199       value = INT_MIN;
200       for ( ply = 1; ply < PLY_MAX - 10; ply++ )
201         {
202           alpha = -score_bound;
203           beta  =  score_bound;
204           
205           value_type = hash_probe( ptree, 1, ply*PLY_INC+PLY_INC/2,
206                                    root_turn, alpha, beta, 0 );
207           if ( value_type != value_exact )   { break; }
208           value = HASH_VALUE;
209       }
210       
211       if ( -score_bound < value )
212         {
213           Out( "- a pv was peeked through the transposition table.\n" );
214           iteration_depth     = ply-1;
215           ptree->pv[0].depth  = (unsigned char)(ply-1);
216           ptree->pv[0].type   = hash_hit;
217           root_value          = value;
218           out_pv( ptree, value, root_turn, 0 );
219           Out( "\n" );
220           
221           if ( ! ptree->pv[0].length )
222             {
223               iteration_depth         = 0;
224               ptree->pv[0].depth = 0;
225               root_value              = -score_bound;
226 #if ! defined(MINIMUM)
227               out_warning( "PEEK FAILED!!!" );
228 #endif
229             }
230         }
231     }
232
233   /* root move generation */
234   {
235     unsigned int elapsed;
236     
237     Out( "- root move generation" );
238     value = make_root_move_list( ptree, flag );
239     if ( game_status & flag_search_error ) { return -1; }
240     if ( game_status & ( flag_quit | flag_quit_ponder | flag_suspend ) )
241       {
242         return 1;
243       }
244
245     if ( ! root_nmove )
246       {
247         str_error = "No legal moves to search";
248         return -2;
249       }
250
251     if ( ! ptree->pv[0].length || ptree->pv[0].a[1] != root_move_list[0].move )
252       {
253         iteration_depth     = 0;
254         ptree->pv[0].a[1]   = root_move_list[0].move;
255         ptree->pv[0].length = 1;
256         ptree->pv[0].depth  = 1;
257         ptree->pv[0].type   = no_rep;
258         root_value          = value;
259       }
260
261 #if defined(MPV)
262     if ( root_mpv )
263       {
264         if ( root_nmove == 1 ) { root_mpv = 0; }
265         easy_abs = 0;
266       }
267 #endif
268
269     if ( get_elapsed( &elapsed ) < 0 ) { return -1; }
270     Out( " ... done (%d moves, %ss)\n",
271          root_nmove, str_time_symple( elapsed - time_start ) );
272   }
273
274
275   /* save preliminary result */
276   assert( root_value != -score_bound );
277   last_root_value = root_turn ? -root_value : root_value;
278   last_pv         = ptree->pv[0];
279
280 #if defined(MNJ_LAN)
281   if ( sckt_mnj != SCKT_NULL )
282     {
283       const char *str = ( root_nmove == 1 ) ? "confident" : "";
284
285       MnjOut( "pid=%d move=%s v=%de n=%" PRIu64 " %s\n",
286               mnj_posi_id, str_CSA_move(ptree->pv[0].a[1]), root_value,
287               ptree->node_searched, str );
288     }
289 #endif
290
291   /* return, if previous pv is long enough */
292   if ( abs(root_value) > score_max_eval
293        || iteration_depth >= depth_limit
294        || ( ( game_status & flag_puzzling )
295             && ( root_nmove == 1 || ptree->pv[0].depth > 4 ) ) )
296     {
297       return 1;
298     }
299
300   if ( ! is_hash_learn_stored )
301     {
302       iret = ini_hash();
303       if ( iret < 0 ) { return iret; }
304     }
305
306   /* iterative deepening search */
307 #if defined(TLP)
308   iret = tlp_start();
309   if ( iret < 0 ) { return iret; }
310 #endif
311   iteration_depth += 1;
312   root_beta        = set_root_beta(  0, root_value );
313   root_alpha       = set_root_alpha( 0, root_value );
314   root_value       = root_alpha;
315   add_rejections( ptree, root_turn, 1 );
316   Out( "- drive an iterative deepening search starting from depth %d\n",
317        iteration_depth );
318
319   for ( ; iteration_depth < 30/*PLY_MAX-10*/; iteration_depth++ ) {
320
321     MnjOut( "pid=%d d=%d\n", mnj_posi_id, iteration_depth );
322
323
324     if ( get_elapsed( &time_last_search ) < 0 ) { return -1; }
325     
326 #if defined(MPV)
327     if ( root_mpv )
328       {
329         int i;
330         i = ( root_nmove < mpv_num ) ? root_nmove : mpv_num;
331         for ( ; i < mpv_num*2; i++ ) { mpv_pv[i].length = 0; }
332       }
333 #endif
334     
335     {
336       unsigned int move;
337       int tt, i, n;
338
339       tt = root_turn;
340       for ( ply = 1; ply <= ptree->pv[0].length; ply++ )
341         {
342           move = ptree->pv[0].a[ply];
343           if ( ! is_move_valid( ptree, move, tt ) )
344             {
345 #if ! defined(MINIMUM)
346               out_warning( "Old pv has an illegal move!  ply=%d, move=%s",
347                            ply, str_CSA_move(move) );
348 #endif
349               break;
350             }
351           MakeMove( tt, move, ply );
352           if ( InCheck(tt) )
353             {
354 #if ! defined(MINIMUM)
355               out_warning( "Old pv has an illegal evasion!  ply=%d, move=%s",
356                            ply, str_CSA_move(move) );
357 #endif
358               UnMakeMove( tt, move, ply );
359               break;
360             }
361           tt = Flip(tt);
362         }
363       for ( ply--; ply > 0; ply-- )
364         {
365           tt   = Flip(tt);
366           move = ptree->pv[0].a[ply];
367           UnMakeMove( tt, move, ply );
368           hash_store_pv( ptree, move, tt );
369         }
370
371       root_nfail_high = 0;
372       root_nfail_low  = 0;
373
374       n = root_nmove;
375       root_move_list[0].status = flag_first;
376       for ( i = 1; i < n; i++ ) { root_move_list[i].status = 0; }
377     }
378
379     /*  a trial of searches  */
380     for ( ;; ) {
381       value = searchr( ptree, root_alpha, root_beta, root_turn,
382                        iteration_depth*PLY_INC + PLY_INC/2 );
383       if ( game_status & flag_search_error ) { return -1; }
384       if ( root_abort )                      { break; }
385
386       assert( abs(value) < score_foul );
387
388       if ( root_beta <= value )
389         {
390           const char *str_move;
391           const char *str;
392           double dvalue;
393           
394           root_move_list[0].status &= ~flag_searched;
395           root_move_list[0].status |= flag_failhigh;
396           dvalue = (double)( root_turn ? -root_beta : root_beta );
397
398           do { root_beta  = set_root_beta( ++root_nfail_high, root_beta ); }
399           while ( value >= root_beta );
400
401           str = str_time_symple( time_last_result - time_start );
402           if ( root_move_list[0].status & flag_first )
403             {
404               Out( "(%2d)%6s %7.2f ", iteration_depth, str, dvalue / 100.0 );
405             }
406           else { Out( "    %6s %7.2f ", str, dvalue / 100.0 ); }
407
408           str = str_fail_high( root_turn, root_nfail_high );
409
410           MnjOut( "pid=%d move=%s v=%dl n=%" PRIu64 "\n", mnj_posi_id,
411                   str_CSA_move(ptree->pv[1].a[1]), root_beta,
412                   ptree->node_searched );
413
414           str_move = str_CSA_move_plus( ptree, ptree->pv[1].a[1], 1,
415                                         root_turn );
416           Out( " 1.%c%s [%s!]\n", ach_turn[root_turn], str_move, str );
417           
418           
419           if ( game_status & flag_pondering )
420             {
421               OutCsaShogi( "info%+.2f %c%s %c%s [%s!]\n",
422                            dvalue / 100.0, ach_turn[Flip(root_turn)],
423                            str_CSA_move(ponder_move),
424                            ach_turn[root_turn], str_move, str );
425             }
426           else {
427             OutCsaShogi( "info%+.2f %c%s [%s!]\n", dvalue / 100.0,
428                          ach_turn[root_turn], str_move, str );
429           }
430         }
431       else if ( value <= root_alpha )
432         {
433           const char *str_move;
434           const char *str;
435           unsigned int time_elapsed;
436           double dvalue;
437
438           if ( ! ( root_move_list[0].status & flag_first ) )
439             {
440               root_value = root_alpha;
441               break;
442             }
443
444           root_move_list[0].status &= ~flag_searched;
445           root_move_list[0].status |= flag_faillow;
446           dvalue = (double)( root_turn ? -root_alpha : root_alpha );
447
448           if ( get_elapsed( &time_elapsed ) < 0 ) { return -1; }
449
450           do { root_alpha = set_root_alpha( ++root_nfail_low, root_alpha ); }
451           while ( value <= root_alpha );
452           root_value = root_alpha;
453           str = str_time_symple( time_elapsed - time_start );
454           Out( "(%2d)%6s %7.2f ", iteration_depth, str, dvalue / 100.0 );
455
456           str      = str_fail_high( Flip(root_turn), root_nfail_low );
457           str_move = str_CSA_move_plus( ptree, root_move_list[0].move, 1,
458                                         root_turn );
459           Out( " 1.%c%s [%s?]\n", ach_turn[root_turn], str_move, str );
460           if ( game_status & flag_pondering )
461             {
462               OutCsaShogi( "info%+.2f %c%s %c%s [%s?]\n",
463                            dvalue / 100.0, ach_turn[Flip(root_turn)],
464                            str_CSA_move(ponder_move),
465                            ach_turn[root_turn], str_move, str );
466             }
467           else {
468             OutCsaShogi( "info%+.2f %c%s [%s?]\n", dvalue / 100.0,
469                          ach_turn[root_turn], str_move, str );
470           }
471         }
472       else { break; }
473     }
474
475     /* the trial of search ended */
476     if ( root_alpha < root_value && root_value < root_beta )
477       {
478         last_root_value = root_turn ? - root_value : root_value;
479         last_pv         = ptree->pv[0];
480       }
481
482     if ( root_abort ) { break; }
483
484     if ( root_alpha < root_value && root_value < root_beta )
485       {
486 #if ! defined(MINIMUM)
487         {
488           int i, n;
489           n = root_nmove;
490           for ( i = 0; i < n; i++ )
491             {
492               if ( root_move_list[i].status & flag_searched ) { continue; }
493               out_warning( "A root move %s is ignored\n",
494                            str_CSA_move(root_move_list[i].move) );
495             }
496         }
497 #endif
498
499         if ( ( game_status & flag_problem ) && depth_limit == PLY_MAX )
500           {
501             if ( is_answer_right( ptree->pv[0].a[1] ) )
502               {
503                 if ( right_answer_made > 1 && iteration_depth > 3 ) { break; }
504                 right_answer_made++;
505               }
506             else { right_answer_made = 0; }
507           }
508         
509         if ( abs(value)      >  score_max_eval ) { break; }
510         if ( iteration_depth >= depth_limit )    { break; }
511         
512         root_beta  = set_root_beta(  0, value );
513         root_alpha = set_root_alpha( 0, value );
514         root_value = root_alpha;
515       }
516 #if ! defined(MINIMUM)
517     else { out_warning(( "SEARCH INSTABILITY IS DETECTED!!!" )); }
518 #endif
519
520     /* shell sort */
521     {
522       root_move_t root_move_swap;
523       const int n = root_nmove;
524       uint64_t sortv;
525       int i, j, k, h;
526       
527       for ( k = SHELL_H_LEN - 1; k >= 0; k-- )
528         {
529           h = ashell_h[k];
530           for ( i = n-h-1; i > 0; i-- )
531             {
532               root_move_swap = root_move_list[i];
533               sortv          = root_move_list[i].nodes;
534               for ( j = i+h; j < n && root_move_list[j].nodes > sortv; j += h )
535                 {
536                   root_move_list[j-h] = root_move_list[j];
537                 }
538               root_move_list[j-h] = root_move_swap;
539             }
540         }
541     }
542   }
543
544   /* iteration ended */
545   sub_rejections( ptree, root_turn, 1 );
546
547   if ( game_status & flag_problem )
548     {
549       if ( is_answer_right( ptree->pv[0].a[1] ) )
550         {
551           right_answer_made = 1;
552         }
553       else { right_answer_made = 0; }
554     }
555
556   {
557     int i;
558     
559     for ( i = 0; i < HIST_SIZE; i++ )
560       {
561         ptree->hist_good[i]  /= 256U;
562         ptree->hist_tried[i] /= 256U;
563       }
564   }
565   /* prunings and extentions-statistics */
566   {
567     double drep, dreject, dhash, dnull, dfh1st;
568
569     drep    = (double)ptree->nperpetual_check;
570     drep   += (double)ptree->nfour_fold_rep;
571     drep   += (double)ptree->nsuperior_rep;
572     drep   *= 100.0 / (double)( ptree->nrep_tried + 1 );
573
574     dreject  = 100.0 * (double)ptree->nreject_done;
575     dreject /= (double)( ptree->nreject_tried + 1 );
576
577     dhash   = (double)ptree->ntrans_exact;
578     dhash  += (double)ptree->ntrans_inferior_hit;
579     dhash  += (double)ptree->ntrans_superior_hit;
580     dhash  += (double)ptree->ntrans_upper;
581     dhash  += (double)ptree->ntrans_lower;
582     dhash  *= 100.0 / (double)( ptree->ntrans_probe + 1 );
583
584     dnull   = 100.0 * (double)ptree->null_pruning_done;
585     dnull  /= (double)( ptree->null_pruning_tried + 1 );
586
587     dfh1st  = 100.0 * (double)ptree->fail_high_first;
588     dfh1st /= (double)( ptree->fail_high + 1 );
589
590     Out( "    pruning  -> rep=%4.2f%%  reject=%4.2f%%\n", drep, dreject );
591     
592     Out( "    pruning  -> hash=%2.0f%%  null=%2.0f%%  fh1st=%4.1f%%\n",
593          dhash, dnull, dfh1st );
594     
595     Out( "    extension-> chk=%u recap=%u 1rep=%u\n",
596          ptree->check_extension_done, ptree->recap_extension_done,
597          ptree->onerp_extension_done );
598   }
599
600   /* futility threashold */
601 #if ! ( defined(NO_STDOUT) && defined(NO_LOGGING) )
602   {
603     int misc   = fmg_misc;
604     int drop   = fmg_drop;
605     int cap    = fmg_cap;
606     int mt     = fmg_mt;
607     int misc_k = fmg_misc_king;
608     int cap_k  = fmg_cap_king;
609     Out( "    futility -> misc=%d drop=%d cap=%d mt=%d misc(k)=%d cap(k)=%d\n",
610          misc, drop, cap, mt, misc_k, cap_k );
611   }
612 #endif
613
614   /* hashing-statistics */
615   {
616     double dalways, dprefer, dsupe, dinfe;
617     double dlower, dupper, dsat;
618     uint64_t word2;
619     int ntrans_table, i, n;
620
621     ntrans_table = 1 << log2_ntrans_table;
622     if ( ntrans_table > 8192 ) { ntrans_table = 8192; }
623     
624     for ( i = 0, n = 0; i < ntrans_table; i++ )
625       {
626         word2 = ptrans_table[i].prefer.word2;
627         SignKey( word2, ptrans_table[i].prefer.word1 );
628         if ( trans_table_age == ( 7 & (int)word2 ) ) { n++; }
629
630         word2 = ptrans_table[i].always[0].word2;
631         SignKey( word2, ptrans_table[i].always[0].word1 );
632         if ( trans_table_age == ( 7 & (int)word2 ) ) { n++; }
633
634         word2 = ptrans_table[i].always[1].word2;
635         SignKey( word2, ptrans_table[i].always[1].word1 );
636         if ( trans_table_age == ( 7 & (int)word2 ) ) { n++; }
637       }
638
639     dalways  = 100.0 * (double)ptree->ntrans_always_hit;
640     dalways /= (double)( ptree->ntrans_probe + 1 );
641
642     dprefer  = 100.0 * (double)ptree->ntrans_prefer_hit;
643     dprefer /= (double)( ptree->ntrans_probe + 1 );
644
645     dsupe    = 100.0 * (double)ptree->ntrans_superior_hit;
646     dsupe   /= (double)( ptree->ntrans_probe + 1 );
647
648     dinfe    = 100.0 * (double)ptree->ntrans_inferior_hit;
649     dinfe   /= (double)( ptree->ntrans_probe + 1 );
650
651     Out( "    hashing  -> always=%2.0f%% prefer=%2.0f%% supe=%4.2f%% "
652          "infe=%4.2f%%\n", dalways, dprefer, dsupe, dinfe );
653
654     dlower  = 100.0 * (double)ptree->ntrans_lower;
655     dlower /= (double)( ptree->ntrans_probe + 1 );
656
657     dupper  = 100.0 * (double)ptree->ntrans_upper;
658     dupper /= (double)( ptree->ntrans_probe + 1 );
659
660     dsat    = 100.0 * (double)n;
661     dsat   /= (double)( 3 * ntrans_table );
662
663     OutCsaShogi( "statsatu=%.0f", dsat );
664     Out( "    hashing  -> "
665          "exact=%d lower=%2.0f%% upper=%4.2f%% sat=%2.0f%% age=%d\n",
666          ptree->ntrans_exact, dlower, dupper, dsat, trans_table_age );
667     if ( dsat > 9.0 ) { trans_table_age  = ( trans_table_age + 1 ) & 0x7; }
668   }
669
670 #if defined(TLP)
671   if ( tlp_max > 1 )
672     {
673       Out( "    threading-> split=%d abort=%d slot=%d\n",
674            tlp_nsplit, tlp_nabort, tlp_nslot+1 );
675       if ( tlp_nslot+1 == TLP_NUM_WORK )
676         {
677           out_warning( "THREAD WORK AREA IS USED UP!!!" );
678         }
679     }
680 #endif
681
682   {
683     double dcpu_percent, dnps, dmat;
684     unsigned int cpu, elapsed;
685
686     Out( "    n=%" PRIu64 " quies=%u eval=%u rep=%u %u(chk) %u(supe)\n",
687          ptree->node_searched, ptree->nquies_called, ptree->neval_called,
688          ptree->nfour_fold_rep, ptree->nperpetual_check,
689          ptree->nsuperior_rep );
690
691     if ( get_cputime( &cpu )     < 0 ) { return -1; }
692     if ( get_elapsed( &elapsed ) < 0 ) { return -1; }
693
694     cpu             -= cpu_start;
695     elapsed         -= time_start;
696
697     dcpu_percent     = 100.0 * (double)cpu;
698     dcpu_percent    /= (double)( elapsed + 1U );
699
700     dnps             = 1000.0 * (double)ptree->node_searched;
701     dnps            /= (double)( elapsed + 1U );
702
703 #if defined(TLP)
704     {
705       double n = (double)tlp_max;
706       node_per_second  = (unsigned int)( ( dnps + 0.5 ) / n );
707     }
708 #else
709     node_per_second  = (unsigned int)( dnps + 0.5 );
710 #endif
711
712     dmat             = (double)MATERIAL;
713     dmat            /= (double)MT_CAP_PAWN;
714
715     OutCsaShogi( " cpu=%.0f nps=%.2f\n", dcpu_percent, dnps / 1e3 );
716     Out( "    time=%s  ", str_time_symple( elapsed ) );
717     Out( "cpu=%3.0f%%  mat=%.1f  nps=%.2fK", dcpu_percent, dmat, dnps / 1e3 );
718     Out( "  time_eff=%s\n\n",
719          str_time_symple( time_last_eff_search - time_start ) );
720   }
721
722   if ( ( game_status & flag_problem ) && ! right_answer_made ) { iret = 0; }
723   else                                                         { iret = 1; }
724
725   return iret;
726 }
727
728
729 static int
730 ini_hash( void )
731 {
732   unsigned int elapsed;
733   int iret;
734
735   if ( time_limit < 150U ) { return 1; }
736   
737   iret = all_hash_learn_store();
738   if ( iret < 0 ) { return iret; }
739   if ( iret )
740     {
741       if ( get_elapsed( &elapsed ) < 0 ) { return -1; }
742       Out( "- load learnt hash values (%ss)\n",
743            str_time_symple( elapsed - time_start ) );
744     }
745
746   return 1;
747 }
748
749
750 static void
751 adjust_fmg( void )
752 {
753   int misc, cap, drop, mt, misc_king, cap_king;
754
755   misc      = fmg_misc      - FMG_MG      / 2;
756   cap       = fmg_cap       - FMG_MG      / 2;
757   drop      = fmg_drop      - FMG_MG      / 2;
758   misc_king = fmg_misc_king - FMG_MG_KING / 2;
759   cap_king  = fmg_cap_king  - FMG_MG_KING / 2;
760   mt        = fmg_mt        - FMG_MG_MT   / 2;
761
762   fmg_misc      = ( misc      < FMG_MISC      ) ? FMG_MISC      : misc;
763   fmg_cap       = ( cap       < FMG_CAP       ) ? FMG_CAP       : cap;
764   fmg_drop      = ( drop      < FMG_DROP      ) ? FMG_DROP      : drop;
765   fmg_misc_king = ( misc_king < FMG_MISC_KING ) ? FMG_MISC_KING : misc_king;
766   fmg_cap_king  = ( cap_king  < FMG_CAP_KING  ) ? FMG_CAP_KING  : cap_king;
767   fmg_mt        = ( mt        < FMG_MT        ) ? FMG_MT        : mt;
768 }
769
770
771 static int
772 set_root_beta( int nfail_high, int root_beta_old )
773 {
774   int aspiration_hwdth, aspiration_fail1;
775
776   if ( time_max_limit != time_limit )
777     {
778       aspiration_hwdth = MT_CAP_DRAGON / 8;
779       aspiration_fail1 = MT_CAP_DRAGON / 2;
780     }
781   else {
782     aspiration_hwdth = MT_CAP_DRAGON / 4;
783     aspiration_fail1 = ( MT_CAP_DRAGON * 3 ) / 4;
784   }
785
786   switch ( nfail_high )
787     {
788     case 0:  root_beta_old += aspiration_hwdth;                     break;
789     case 1:  root_beta_old += aspiration_fail1 - aspiration_hwdth;  break;
790     case 2:  root_beta_old  = score_bound;                          break;
791     default:
792       out_error( "Error at set_root_beta!" );
793       exit(1);
794     }
795   if ( root_beta_old > score_max_eval ) { root_beta_old = score_bound; }
796
797   return root_beta_old;
798 }
799
800
801 static int
802 set_root_alpha( int nfail_low, int root_alpha_old )
803 {
804   int aspiration_hwdth, aspiration_fail1;
805
806   if ( time_max_limit != time_limit )
807     {
808       aspiration_hwdth = MT_CAP_DRAGON / 8;
809       aspiration_fail1 = MT_CAP_DRAGON / 2;
810     }
811   else {
812     aspiration_hwdth = MT_CAP_DRAGON / 4;
813     aspiration_fail1 = ( MT_CAP_DRAGON * 3 ) / 4;
814   }
815
816   switch ( nfail_low )
817     {
818     case 0:  root_alpha_old -= aspiration_hwdth;                     break;
819     case 1:  root_alpha_old -= aspiration_fail1 - aspiration_hwdth;  break;
820     case 2:  root_alpha_old  = -score_bound;                         break;
821     default:
822       out_error( "Error at set_root_alpha!" );
823       exit(1);
824     }
825   if ( root_alpha_old < -score_max_eval ) { root_alpha_old = -score_bound; }
826
827   return root_alpha_old;
828 }
829
830
831 static const char *
832 str_fail_high( int turn, int nfail_high )
833 {
834   const char *str;
835
836   if ( time_max_limit != time_limit )
837     {
838       if ( nfail_high == 1 ) { str = turn ? "-1" : "+1"; }
839       else                   { str = turn ? "-4" : "+4"; }
840     }
841   else {
842     if ( nfail_high == 1 ) { str = turn ? "-2" : "+2"; }
843     else                   { str = turn ? "-6" : "+6"; }
844   }
845   return str;
846 }
847
848
849 static int
850 is_answer_right( unsigned int move )
851 {
852   const char *str_anser;
853   const char *str_move;
854   int ianser, iret;
855   
856   iret     = 0;
857   str_move = str_CSA_move( move );
858
859   for ( ianser = 0; ianser < MAX_ANSWER; ianser++ )
860     {
861       str_anser = &( record_problems.info.str_move[ianser][0] );
862       if ( str_anser[0] == '\0' ) { break; }
863       if ( ! strcmp( str_anser+1, str_move ) )
864         {
865           iret = 1;
866           break;
867         }
868     }
869
870   return iret;
871 }