Fix Linux sigint problem
[bonanza.git] / swap.c
1 #include <stdlib.h>
2 #include <limits.h>
3 #include "shogi.h"
4
5 int
6 swap( const tree_t * restrict ptree, unsigned int move, int root_alpha,
7       int root_beta, int turn )
8 {
9   bitboard_t bb, bb_temp, bb_attack;
10   unsigned int uattack;
11   int attacked_piece, from, to, nc, ir0;
12   int piece_cap, piece, value, xvalue, alpha, beta, is_promo;
13
14   from = (int)I2From( move );
15   to   = (int)I2To( move );
16
17   if ( from >= nsquare )
18     {
19       value          = 0;
20       piece          = From2Drop( from );
21       attacked_piece = p_value_ex[15+piece];
22     }
23   else {
24     piece     = (int)I2PieceMove( move );
25     piece_cap = (int)UToCap( move );
26     is_promo  = (int)I2IsPromote( move );
27     
28     value          = p_value_ex[15+piece_cap];
29     attacked_piece = p_value_ex[15+piece];
30     if ( is_promo )
31       {
32         value          += benefit2promo[7+piece];
33         attacked_piece += benefit2promo[7+piece];
34       }
35     xvalue = value - attacked_piece - MT_PRO_PAWN;
36     if ( xvalue >= root_beta ) { return xvalue; }
37   }
38
39   bb_attack = attacks_to_piece( ptree, to );
40   alpha     = INT_MIN;
41   beta      = value;
42   for ( nc = 1;; nc++ )
43     {
44       /* remove an attacker, and add a hidden piece to attack bitmap */
45       if ( from < nsquare )
46         {
47           Xor( from, bb_attack );
48           switch ( adirec[to][from] )
49             {
50             case direc_rank:
51               ir0     = aslide[from].ir0;
52               uattack = AttackRank( from );
53               if ( from > to ) { uattack &= abb_plus_rays[from].p[ir0]; }
54               else               { uattack &= abb_minus_rays[from].p[ir0]; }
55               uattack &= BB_B_RD.p[ir0] |  BB_W_RD.p[ir0];
56               bb_attack.p[ir0] |= uattack;
57               break;
58
59             case direc_file:
60               bb = AttackFile( from );
61               BBOr( bb_temp, BB_B_RD, BB_W_RD );
62               if ( from > to )
63                 {
64                   BBOr( bb_temp, bb_temp, BB_BLANCE );
65                   BBAnd( bb, bb, abb_plus_rays[from] );
66                 }
67               else {
68                 BBOr( bb_temp, bb_temp, BB_WLANCE );
69                 BBAnd( bb, bb, abb_minus_rays[from] );
70               }
71               BBAnd( bb, bb, bb_temp );
72               BBOr( bb_attack, bb_attack, bb );
73               break;
74               
75             case direc_diag1:
76               bb = AttackDiag1( from );
77               if ( from > to ) { BBAnd( bb, bb, abb_plus_rays[from] ); }
78               else               { BBAnd( bb, bb, abb_minus_rays[from] ); }
79               BBOr( bb_temp, BB_B_BH, BB_W_BH );
80               BBAnd( bb, bb, bb_temp );
81               BBOr( bb_attack, bb_attack, bb );
82               break;
83               
84             case direc_diag2:
85               bb = AttackDiag2( from );
86               if ( from > to ) { BBAnd( bb, bb, abb_plus_rays[from] ); }
87               else               { BBAnd( bb, bb, abb_minus_rays[from] ); }
88               BBOr( bb_temp, BB_B_BH, BB_W_BH );
89               BBAnd( bb, bb, bb_temp );
90               BBOr( bb_attack, bb_attack, bb );
91               break;
92               
93             }
94         }
95       if ( ! BBToU( bb_attack ) ) { break; }
96
97       /* find a cheapest piece attacking the target */
98       turn  = Flip( turn );
99       value = attacked_piece - value;
100       if ( turn )
101         {
102           if( BBContract( bb_attack, BB_WPAWN ) )
103             {
104               from           = to-nfile;
105               attacked_piece = MT_CAP_PAWN;
106               if ( to > 53 )
107                 {
108                   value          += MT_PRO_PAWN;
109                   attacked_piece += MT_PRO_PAWN;
110                 }
111               goto ab_cut;
112             }
113           BBAnd( bb, BB_WLANCE, bb_attack );
114           if( BBToU( bb ) )
115             {
116               from           = FirstOne( bb );
117               attacked_piece = MT_CAP_LANCE;
118               if ( to > 53 )
119                 {
120                   value          += MT_PRO_LANCE;
121                   attacked_piece += MT_PRO_LANCE;
122                 }
123               goto ab_cut;
124             }
125           BBAnd( bb, BB_WKNIGHT, bb_attack );
126           if( BBToU( bb ) )
127             {
128               from           = FirstOne( bb );
129               attacked_piece = MT_CAP_KNIGHT;
130               if ( to > 53 )
131                 {
132                   value          += MT_PRO_KNIGHT;
133                   attacked_piece += MT_PRO_KNIGHT;
134                 }
135               goto ab_cut;
136             }
137           BBAnd( bb, BB_WPRO_PAWN, bb_attack );
138           if( BBToU( bb ) )
139             {
140               from           = FirstOne( bb );
141               attacked_piece = MT_CAP_PRO_PAWN;
142               goto ab_cut;
143             }
144           BBAnd( bb, BB_WPRO_LANCE, bb_attack );
145           if( BBToU( bb ) )
146             {
147               from           = FirstOne( bb );
148               attacked_piece = MT_CAP_PRO_LANCE;
149               goto ab_cut;
150             }
151           BBAnd( bb, BB_WPRO_KNIGHT, bb_attack );
152           if( BBToU( bb ) )
153             {
154               from           = FirstOne( bb );
155               attacked_piece = MT_CAP_PRO_KNIGHT;
156               goto ab_cut;
157             }
158           BBAnd( bb, BB_WSILVER, bb_attack );
159           if( BBToU( bb ) )
160             {
161               from          = FirstOne( bb );
162               attacked_piece = MT_CAP_SILVER;
163               if ( from > 53 || to > 53 )
164                 {
165                   value          += MT_PRO_SILVER;
166                   attacked_piece += MT_PRO_SILVER;
167                 }
168               goto ab_cut;
169             }
170           BBAnd( bb, BB_WPRO_SILVER, bb_attack );
171           if( BBToU( bb ) )
172             {
173               from           = FirstOne( bb );
174               attacked_piece = MT_CAP_PRO_SILVER;
175               goto ab_cut;
176             }
177           BBAnd( bb, BB_WGOLD, bb_attack );
178           if( BBToU( bb ) )
179             {
180               from           = FirstOne( bb );
181               attacked_piece = MT_CAP_GOLD;
182               goto ab_cut;
183             }
184           BBAnd( bb, BB_WBISHOP, bb_attack );
185           if( BBToU( bb ) )
186             {
187               from           = FirstOne( bb );
188               attacked_piece = MT_CAP_BISHOP;
189               if ( from > 53 || to > 53 )
190                 {
191                   value          += MT_PRO_BISHOP;
192                   attacked_piece += MT_PRO_BISHOP;
193                 }
194               goto ab_cut;
195             }
196           BBAnd( bb, BB_WHORSE, bb_attack );
197           if( BBToU( bb ) )
198             {
199               from           = FirstOne( bb );
200               attacked_piece = MT_CAP_HORSE;
201               goto ab_cut;
202             }
203           BBAnd( bb, BB_WROOK, bb_attack );
204           if( BBToU( bb ) )
205             {
206               from           = FirstOne( bb );
207               attacked_piece = MT_CAP_ROOK;
208               if ( from > 53 || to > 53 )
209                 {
210                   value          += MT_PRO_ROOK;
211                   attacked_piece += MT_PRO_ROOK;
212                 }
213               goto ab_cut;
214             }
215           BBAnd( bb, BB_WDRAGON, bb_attack );
216           if( BBToU( bb ) )
217             {
218               from           = FirstOne( bb );
219               attacked_piece = MT_CAP_DRAGON;
220               goto ab_cut;
221             }
222           if( BBContract( bb_attack, BB_WKING ) )
223             {
224               from           = SQ_WKING;
225               attacked_piece = MT_CAP_KING;
226               goto ab_cut;
227             }
228         }
229       else {
230         if( BBContract( bb_attack, BB_BPAWN ) )
231           {
232             from           = to+nfile;
233             attacked_piece = MT_CAP_PAWN;
234             if ( to < 27 )
235               {
236                 value          += MT_PRO_PAWN;
237                 attacked_piece += MT_PRO_PAWN;
238               }
239             goto ab_cut;
240           }
241         BBAnd( bb, BB_BLANCE, bb_attack );
242         if( BBToU( bb ) )
243           {
244             from           = FirstOne( bb );
245             attacked_piece = MT_CAP_LANCE;
246             if ( to < 27 )
247               {
248                 value          += MT_PRO_LANCE;
249                 attacked_piece += MT_PRO_LANCE;
250               }
251             goto ab_cut;
252           }
253         BBAnd( bb, BB_BKNIGHT, bb_attack );
254         if( BBToU( bb ) )
255           {
256             from           = FirstOne( bb );
257             attacked_piece = MT_CAP_KNIGHT;
258             if ( to < 27 )
259               {
260                 value          += MT_PRO_KNIGHT;
261                 attacked_piece += MT_PRO_KNIGHT;
262               }
263             goto ab_cut;
264           }
265         BBAnd( bb, BB_BPRO_PAWN, bb_attack );
266         if( BBToU( bb ) )
267           {
268             from           = FirstOne( bb );
269             attacked_piece = MT_CAP_PRO_PAWN;
270             goto ab_cut;
271           }
272         BBAnd( bb, BB_BPRO_LANCE, bb_attack );
273         if( BBToU( bb ) )
274           {
275             from           = FirstOne( bb );
276             attacked_piece = MT_CAP_PRO_LANCE;
277             goto ab_cut;
278           }
279         BBAnd( bb, BB_BPRO_KNIGHT, bb_attack );
280         if( BBToU( bb ) )
281           {
282             from           = FirstOne( bb );
283             attacked_piece = MT_CAP_PRO_KNIGHT;
284             goto ab_cut;
285           }
286         BBAnd( bb, BB_BSILVER, bb_attack );
287         if( BBToU( bb ) )
288           {
289             from           = FirstOne( bb );
290             attacked_piece = MT_CAP_SILVER;
291             if ( from < 27 || to < 27 )
292               {
293                 value          += MT_PRO_SILVER;
294                 attacked_piece += MT_PRO_SILVER;
295               }
296             goto ab_cut;
297           }
298         BBAnd( bb, BB_BPRO_SILVER, bb_attack );
299         if( BBToU( bb ) )
300           {
301             from           = FirstOne( bb );
302             attacked_piece = MT_CAP_PRO_SILVER;
303             goto ab_cut;
304           }
305         BBAnd( bb, BB_BGOLD, bb_attack );
306         if( BBToU( bb ) )
307           {
308             from           = FirstOne( bb );
309             attacked_piece = MT_CAP_GOLD;
310             goto ab_cut;
311           }
312         BBAnd( bb, BB_BBISHOP, bb_attack );
313         if( BBToU( bb ) )
314           {
315             from          = FirstOne( bb );
316             attacked_piece = MT_CAP_BISHOP;
317             if ( from < 27 || to < 27 )
318               {
319                 value          += MT_PRO_BISHOP;
320                 attacked_piece += MT_PRO_BISHOP;
321               }
322             goto ab_cut;
323           }
324         BBAnd( bb, BB_BHORSE, bb_attack );
325         if( BBToU( bb ) )
326           {
327             from           = FirstOne( bb );
328             attacked_piece = MT_CAP_HORSE;
329             goto ab_cut;
330           }
331         BBAnd( bb, BB_BROOK, bb_attack );
332         if( BBToU( bb ) )
333           {
334             from           = FirstOne( bb );
335             attacked_piece = MT_CAP_ROOK;
336             if ( from < 27 || to < 27 )
337               {
338                 value          += MT_PRO_ROOK;
339                 attacked_piece += MT_PRO_ROOK;
340               }
341             goto ab_cut;
342           }
343         BBAnd( bb, BB_BDRAGON, bb_attack );
344         if( BBToU( bb ) )
345           {
346             from           = FirstOne( bb );
347             attacked_piece = MT_CAP_DRAGON;
348             goto ab_cut;
349           }
350         if( BBContract( bb_attack, BB_BKING ) )
351           {
352             from           = SQ_BKING;
353             attacked_piece = MT_CAP_KING;
354             goto ab_cut;
355           }
356       }
357       break;
358
359     ab_cut:
360       if ( nc & 1 )
361         {
362           if ( -value > alpha )
363             {
364               if ( -value >= beta )      { return beta; }
365               if ( -value >= root_beta ) { return -value; }
366               alpha = -value;
367             }
368           else {
369             xvalue = attacked_piece + MT_PRO_PAWN - value;
370             if ( xvalue <= alpha )      { return alpha; }
371             if ( xvalue <= root_alpha ) { return xvalue; }
372           }
373         }
374       else {
375         if ( value < beta )
376           {
377             if ( value <= alpha )      { return alpha; }
378             if ( value <= root_alpha ) { return value; }
379             beta = value;
380           }
381         else {
382           xvalue = value - attacked_piece - MT_PRO_PAWN;
383           if ( xvalue >= beta )      { return beta; }
384           if ( xvalue >= root_beta ) { return xvalue; }
385         }
386       }
387     }
388
389   if ( nc & 1 ) { return beta; }
390   else          { return alpha; }
391 }