Fix Linux sigint problem
[bonanza.git] / root.c
1 #include <stdlib.h>
2 #include <limits.h>
3 #include "shogi.h"
4
5 static int read_rest_list( tree_t * restrict ptree,
6                            unsigned int * restrict pmove_list );
7
8 static int is_move_rest( unsigned int move,
9                          const unsigned int * restrict pmove_restraint );
10
11 int
12 make_root_move_list( tree_t * restrict ptree, int flag )
13 {
14   unsigned int * restrict pmove;
15   unsigned int arestraint_list[ MAX_LEGAL_MOVES ];
16   int asort[ MAX_LEGAL_MOVES ];
17   unsigned int move, move_best;
18   int i, j, k, h, value, num_root_move, iret, value_pre_pv;
19   int value_best;
20
21   if ( flag & flag_refer_rest ) { read_rest_list( ptree, arestraint_list ); }
22   else                          { arestraint_list[0] = 0; }
23
24   pmove = ptree->move_last[0];
25   ptree->move_last[1] = GenCaptures( root_turn, pmove );
26   ptree->move_last[1] = GenNoCaptures( root_turn, ptree->move_last[1] );
27   ptree->move_last[1] = GenDrop( root_turn, ptree->move_last[1] );
28   num_root_move = (int)( ptree->move_last[1] - pmove );
29
30   value_pre_pv = INT_MIN;
31   move_best    = 0;
32   value_best   = 0;
33   for ( i = 0; i < num_root_move; i++ )
34     {
35       if ( ! ( game_status & flag_nopeek )
36            && ( game_status & ( flag_puzzling | flag_pondering ) )
37            && i != 0
38            && ( i % 8 ) == 0 )
39         {
40           iret = next_cmdline( 0 );
41           if ( iret == -1 )
42             {
43               game_status |= flag_search_error;
44               return 1;
45             }
46           else if ( iret == -2 )
47             {
48               out_warning( "%s", str_error );
49               ShutdownClient;
50             }
51           else if ( game_status & flag_quit ) { return 1; }
52           else if ( iret )
53             {
54               iret = procedure( ptree );
55               if ( iret == -1 )
56                 {
57                   game_status |= flag_search_error;
58                   next_cmdline( 1 );
59                   return 1;
60                 }
61               else if ( iret == -2 )
62                 {
63                   out_warning( "%s", str_error );
64                   next_cmdline( 1 );
65                   ShutdownClient;
66                 }
67               else if ( iret == 1 ) { next_cmdline( 1 ); }
68
69               if ( game_status & ( flag_quit | flag_quit_ponder
70                                    | flag_suspend ) )
71                 {
72                   return 1;
73                 }
74             }
75         }
76
77       value = INT_MIN;
78       move  = pmove[i];
79
80       MakeMove( root_turn, move, 1 );
81       if ( ! InCheck( root_turn )
82            && ! is_move_rest( move, arestraint_list ) )
83         {
84           iret = no_rep;
85           if ( InCheck(Flip(root_turn)) )
86             {
87               ptree->nsuc_check[2]
88                 = (unsigned char)( ptree->nsuc_check[0] + 1U );
89               if ( ptree->nsuc_check[2] >= 2 * 2 )
90                 {
91                   iret = detect_repetition( ptree, 2, Flip(root_turn), 2 );
92                 }
93             }
94
95           if ( iret == perpetual_check ) { value = INT_MIN; }
96           else {
97             ptree->current_move[1] = move;
98             value = -search_quies( ptree, -score_bound, score_bound,
99                                    Flip(root_turn), 2, 1 );
100             if ( value > value_best )
101               {
102                 value_best = value;
103                 move_best  = move;
104               }
105             if ( I2IsPromote(move) ) { value++; }
106             if ( move == ptree->pv[0].a[1] )
107               {
108                 value_pre_pv = value;
109                 value        = INT_MAX;
110               }
111           }
112         }
113       UnMakeMove( root_turn, move, 1 );
114       asort[i] = value;
115     }
116   if ( UToCap(move_best) ) { root_move_cap = 1; }
117
118   /* shell sort */
119   for ( k = SHELL_H_LEN - 1; k >= 0; k-- )
120     {
121       h = ashell_h[k];
122       for ( i = num_root_move-h-1; i >= 0; i-- )
123         {
124           value = asort[i];
125           move  = pmove[i];
126           for ( j = i+h; j < num_root_move && asort[j] > value; j += h )
127             {
128               asort[j-h] = asort[j];
129               pmove[j-h] = pmove[j];
130             }
131           asort[j-h] = value;
132           pmove[j-h] = move;
133         }
134     }
135
136   /* discard all of moves cause mate or perpetual check */
137   if ( asort[0] >= -score_max_eval )
138     {
139       for ( ; num_root_move; num_root_move-- )
140         {
141           if ( asort[num_root_move-1] >= -score_max_eval ) { break; }
142         }
143     }
144
145   /* discard perpetual checks */
146   else for ( ; num_root_move; num_root_move-- )
147     {
148       if ( asort[num_root_move-1] != INT_MIN ) { break; }
149     }
150
151   for ( i = 0; i < num_root_move; i++ )
152     {
153       root_move_list[i].move   = pmove[i];
154       root_move_list[i].nodes  = 0;
155       root_move_list[i].status = 0;
156     }
157   if ( value_pre_pv != INT_MIN ) { asort[0] = value_pre_pv; }
158   root_nmove = num_root_move;
159
160   if ( num_root_move > 1 && ! ( game_status & flag_puzzling ) )
161     {
162       int id_easy_move = 0;
163
164       if ( asort[0] > asort[1] + ( MT_CAP_DRAGON * 3 ) / 8 )
165         {
166           id_easy_move = 3;
167           easy_min     = - ( MT_CAP_DRAGON *  4 ) / 16;
168           easy_max     =   ( MT_CAP_DRAGON * 32 ) / 16;
169           easy_abs     =   ( MT_CAP_DRAGON * 19 ) / 16;
170         }
171       else if ( asort[0] > asort[1] + ( MT_CAP_DRAGON * 2 ) / 8 )
172         {
173           id_easy_move = 2;
174           easy_min     = - ( MT_CAP_DRAGON *  3 ) / 16;
175           easy_max     =   ( MT_CAP_DRAGON *  6 ) / 16;
176           easy_abs     =   ( MT_CAP_DRAGON *  9 ) / 16;
177         }
178       else if ( asort[0] > asort[1] + MT_CAP_DRAGON / 8
179                 && asort[0] > - MT_CAP_DRAGON / 8
180                 && I2From(pmove[0]) < nsquare )
181         {
182           id_easy_move = 1;
183           easy_min     = - ( MT_CAP_DRAGON *  2 ) / 16;
184           easy_max     =   ( MT_CAP_DRAGON *  4 ) / 16;
185           easy_abs     =   ( MT_CAP_DRAGON *  6 ) / 16;
186         }
187
188       if ( easy_abs )
189         {
190           Out( "\n    the root move %s looks easy (type %d).\n",
191                str_CSA_move(pmove[0]), id_easy_move );
192           Out( "    evasion:%d, capture:%d, promotion:%d, drop:%d, "
193                "value:%5d - %5d\n",
194                ptree->nsuc_check[1]        ? 1 : 0,
195                UToCap(pmove[0])            ? 1 : 0,
196                I2IsPromote(pmove[0])       ? 1 : 0,
197                I2From(pmove[0]) >= nsquare ? 1 : 0,
198                asort[0], asort[1] );
199           easy_value = asort[0];
200         }
201     }
202
203   return asort[0];
204 }
205
206
207 static int
208 read_rest_list( tree_t * restrict ptree, unsigned int * restrict pmove_list )
209 {
210   FILE *pf;
211   int iret, imove;
212   char a[65536];
213
214   pf = file_open( "restraint.dat", "r" );
215   if ( pf == NULL ) { return -2; }
216
217   for ( imove = 0; imove < MAX_LEGAL_MOVES; imove++ )
218     {
219 #if defined(_MSC_VER)
220       iret = fscanf_s( pf, "%s\n", a, 65536 );
221 #else
222       iret = fscanf( pf, "%s\n", a );
223 #endif
224       if ( iret != 1 ) { break; }
225       iret = interpret_CSA_move( ptree, pmove_list+imove, a );
226       if ( iret < 0 )
227         {
228           file_close( pf );
229           return iret;
230         }
231     }
232
233   pmove_list[imove] = 0;
234
235   return file_close( pf );
236 }
237
238
239 static int
240 is_move_rest( unsigned int move,
241               const unsigned int * restrict pmove_restraint )
242 {
243   while ( *pmove_restraint )
244     {
245       if ( move == *pmove_restraint++ ) { return 1; }
246     }
247
248   return 0;
249 }