Force iteration to start at 1 in analyze mode
[bonanza.git] / makemove.c
1 #include <assert.h>
2 #include <string.h>
3 #include "shogi.h"
4
5 #define DropB( PIECE, piece )  Xor( to, BB_B ## PIECE );                    \
6                                HASH_KEY    ^= ( b_ ## piece ## _rand )[to]; \
7                                HAND_B      -= flag_hand_ ## piece;          \
8                                BOARD[to]  = piece
9
10 #define DropW( PIECE, piece )  Xor( to, BB_W ## PIECE );                    \
11                                HASH_KEY    ^= ( w_ ## piece ## _rand )[to]; \
12                                HAND_W      -= flag_hand_ ## piece;          \
13                                BOARD[to]  = - piece
14
15 #define CapB( PIECE, piece, pro_piece )                   \
16           Xor( to, BB_B ## PIECE );                       \
17           HASH_KEY  ^= ( b_ ## pro_piece ## _rand )[to];  \
18           HAND_W    += flag_hand_ ## piece;               \
19           MATERIAL  -= MT_CAP_ ## PIECE
20
21 #define CapW( PIECE, piece, pro_piece )                   \
22           Xor( to, BB_W ## PIECE );                       \
23           HASH_KEY  ^= ( w_ ## pro_piece ## _rand )[to];  \
24           HAND_B    += flag_hand_ ## piece;               \
25           MATERIAL  += MT_CAP_ ## PIECE
26
27 #define NocapProB( PIECE, PRO_PIECE, piece, pro_piece )       \
28           Xor( from, BB_B ## PIECE );                         \
29           Xor( to,   BB_B ## PRO_PIECE );                     \
30           HASH_KEY    ^= ( b_ ## pro_piece ## _rand )[to]     \
31                        ^ ( b_ ## piece     ## _rand )[from];  \
32           MATERIAL    += MT_PRO_ ## PIECE;                    \
33           BOARD[to] = pro_piece
34
35 #define NocapProW( PIECE, PRO_PIECE, piece, pro_piece )       \
36           Xor( from, BB_W ## PIECE );                         \
37           Xor( to,   BB_W ## PRO_PIECE );                     \
38           HASH_KEY    ^= ( w_ ## pro_piece ## _rand )[to]     \
39                        ^ ( w_ ## piece     ## _rand )[from];  \
40           MATERIAL    -= MT_PRO_ ## PIECE;                    \
41           BOARD[to]  = - pro_piece
42  
43 #define NocapNoproB( PIECE, piece )                          \
44           SetClear( BB_B ## PIECE );                         \
45           HASH_KEY    ^= ( b_ ## piece ## _rand )[to]        \
46                        ^ ( b_ ## piece ## _rand )[from];     \
47           BOARD[to] = piece
48
49 #define NocapNoproW( PIECE, piece )                          \
50           SetClear( BB_W ## PIECE );                         \
51           HASH_KEY    ^= ( w_ ## piece ## _rand )[to]        \
52                        ^ ( w_ ## piece ## _rand )[from];     \
53           BOARD[to] = - piece
54
55
56 void
57 make_move_b( tree_t * restrict ptree, unsigned int move, int ply )
58 {
59   const int from = (int)I2From(move);
60   const int to   = (int)I2To(move);
61   const int nrep  = root_nrep + ply - 1;
62
63   assert( UToCap(move) != king );
64   assert( move );
65   assert( is_move_valid( ptree, move, black ) );
66
67   ptree->rep_board_list[nrep]    = HASH_KEY;
68   ptree->rep_hand_list[nrep]     = HAND_B;
69   ptree->save_material[ply]      = (short)MATERIAL;
70   ptree->stand_pat[ply+1]        = score_bound;
71
72   if ( from >= nsquare )
73     {
74       switch ( From2Drop(from) )
75         {
76         case pawn:   Xor( to-nfile, BB_BPAWN_ATK );
77                      DropB( PAWN,   pawn   );  break;
78         case lance:  DropB( LANCE,  lance  );  break;
79         case knight: DropB( KNIGHT, knight );  break;
80         case silver: DropB( SILVER, silver );  break;
81         case gold:   DropB( GOLD,   gold   );
82                      Xor( to, BB_BTGOLD );     break;
83         case bishop: DropB( BISHOP, bishop );
84                      Xor( to, BB_B_BH );       break;
85         default:     assert( From2Drop(from) == rook );
86                      DropB( ROOK,  rook );
87                      Xor( to, BB_B_RD );       break;
88         }
89       Xor( to, BB_BOCCUPY );
90       XorFile( to, OCCUPIED_FILE );
91       XorDiag2( to, OCCUPIED_DIAG2 );
92       XorDiag1( to, OCCUPIED_DIAG1 );
93     }
94   else {
95     const int ipiece_move = (int)I2PieceMove(move);
96     const int ipiece_cap  = (int)UToCap(move);
97     const int is_promote  = (int)I2IsPromote(move);
98     bitboard_t bb_set_clear;
99
100     BBOr( bb_set_clear, abb_mask[from], abb_mask[to] );
101     SetClear( BB_BOCCUPY );
102     BOARD[from] = empty;
103
104     if ( is_promote ) switch( ipiece_move )
105       {
106       case pawn:   Xor( to, BB_BPAWN_ATK );
107                    Xor( to, BB_BTGOLD );
108                    NocapProB( PAWN,   PRO_PAWN,   pawn,   pro_pawn );   break;
109       case lance:  Xor( to, BB_BTGOLD );
110                    NocapProB( LANCE,  PRO_LANCE,  lance,  pro_lance );  break;
111       case knight: Xor( to, BB_BTGOLD );
112                    NocapProB( KNIGHT, PRO_KNIGHT, knight, pro_knight ); break;
113       case silver: Xor( to, BB_BTGOLD );
114                    NocapProB( SILVER, PRO_SILVER, silver, pro_silver ); break;
115       case bishop: Xor( to, BB_B_HDK );
116                    SetClear( BB_B_BH );
117                    NocapProB( BISHOP, HORSE,      bishop, horse );      break;
118       default:     assert( ipiece_move == rook );
119                    Xor( to, BB_B_HDK );
120                    SetClear( BB_B_RD );
121                    NocapProB( ROOK,   DRAGON,     rook,   dragon );     break;
122       }
123     else switch ( ipiece_move )
124       {
125       case pawn:       Xor( to-nfile, BB_BPAWN_ATK );
126                        Xor( to,       BB_BPAWN_ATK );
127                        NocapNoproB( PAWN,   pawn);       break;
128       case lance:      NocapNoproB( LANCE,  lance);      break;
129       case knight:     NocapNoproB( KNIGHT, knight);     break;
130       case silver:     NocapNoproB( SILVER, silver);     break;
131       case gold:       NocapNoproB( GOLD,   gold);
132                        SetClear( BB_BTGOLD );             break;
133       case bishop:     SetClear( BB_B_BH );
134                        NocapNoproB( BISHOP, bishop);     break;
135       case rook:       NocapNoproB( ROOK,   rook);
136                        SetClear( BB_B_RD );                break;
137       case king:       HASH_KEY ^= b_king_rand[to] ^ b_king_rand[from];
138                        SetClear( BB_B_HDK );
139                        BOARD[to] = king;
140                        SQ_BKING  = (char)to;           break;
141       case pro_pawn:   NocapNoproB( PRO_PAWN, pro_pawn );
142                        SetClear( BB_BTGOLD );             break;
143       case pro_lance:  NocapNoproB( PRO_LANCE, pro_lance );
144                        SetClear( BB_BTGOLD );             break;
145       case pro_knight: NocapNoproB( PRO_KNIGHT, pro_knight );
146                        SetClear( BB_BTGOLD );             break;
147       case pro_silver: NocapNoproB( PRO_SILVER, pro_silver );
148                        SetClear( BB_BTGOLD );             break;
149       case horse:      NocapNoproB( HORSE, horse );
150                        SetClear( BB_B_HDK );
151                        SetClear( BB_B_BH );                break;
152       default:         assert( ipiece_move == dragon );
153                        NocapNoproB( DRAGON, dragon );
154                        SetClear( BB_B_HDK );
155                        SetClear( BB_B_RD );                break;
156       }
157     
158     if ( ipiece_cap )
159       {
160         switch( ipiece_cap )
161           {
162           case pawn:       CapW( PAWN, pawn, pawn );
163                            Xor( to+nfile, BB_WPAWN_ATK );               break;
164           case lance:      CapW( LANCE,  lance, lance );       break;
165           case knight:     CapW( KNIGHT, knight, knight );      break;
166           case silver:     CapW( SILVER, silver, silver );      break;
167           case gold:       CapW( GOLD,   gold,   gold );
168                            Xor( to, BB_WTGOLD );                       break;
169           case bishop:     CapW( BISHOP, bishop, bishop );
170                            Xor( to, BB_W_BH );                          break;
171           case rook:       CapW( ROOK, rook, rook);
172                            Xor( to, BB_W_RD );                          break;
173           case pro_pawn:   CapW( PRO_PAWN, pawn, pro_pawn );
174                            Xor( to, BB_WTGOLD );                       break;
175           case pro_lance:  CapW( PRO_LANCE, lance, pro_lance );
176                            Xor( to, BB_WTGOLD );                       break;
177           case pro_knight: CapW( PRO_KNIGHT, knight, pro_knight );
178                            Xor( to, BB_WTGOLD );                       break;
179           case pro_silver: CapW( PRO_SILVER, silver, pro_silver );
180                            Xor( to, BB_WTGOLD );                       break;
181           case horse:      CapW( HORSE, bishop, horse );
182                            Xor( to, BB_W_HDK );
183                            Xor( to, BB_W_BH );                          break;
184           default:         assert( ipiece_cap == dragon );
185                            CapW( DRAGON, rook, dragon );
186                            Xor( to, BB_W_HDK );
187                            Xor( to, BB_W_RD );                         break;
188           }
189         Xor( to, BB_WOCCUPY );
190         XorFile( from, OCCUPIED_FILE );
191         XorDiag2( from, OCCUPIED_DIAG2 );
192         XorDiag1( from, OCCUPIED_DIAG1 );
193       }
194     else {
195       SetClearFile( from, to, OCCUPIED_FILE );
196       SetClearDiag1( from, to, OCCUPIED_DIAG1 );
197       SetClearDiag2( from, to, OCCUPIED_DIAG2 );
198     }
199   }
200
201   assert( exam_bb( ptree ) );
202 }
203
204
205 void
206 make_move_w( tree_t * restrict ptree, unsigned int move, int ply )
207 {
208   const int from = (int)I2From(move);
209   const int to   = (int)I2To(move);
210   const int nrep  = root_nrep + ply - 1;
211
212   assert( UToCap(move) != king );
213   assert( move );
214   assert( is_move_valid( ptree, move, white ) );
215
216   ptree->rep_board_list[nrep]    = HASH_KEY;
217   ptree->rep_hand_list[nrep]     = HAND_B;
218   ptree->save_material[ply]      = (short)MATERIAL;
219   ptree->stand_pat[ply+1]        = score_bound;
220
221   if ( from >= nsquare )
222     {
223       switch( From2Drop(from) )
224         {
225         case pawn:   Xor( to+nfile, BB_WPAWN_ATK );
226                      DropW( PAWN,   pawn );    break;
227         case lance:  DropW( LANCE,  lance );   break;
228         case knight: DropW( KNIGHT, knight );  break;
229         case silver: DropW( SILVER, silver );  break;
230         case gold:   DropW( GOLD,   gold );
231                      Xor( to, BB_WTGOLD );     break;
232         case bishop: DropW( BISHOP, bishop );
233                      Xor( to, BB_W_BH );       break;
234         default:     DropW( ROOK,   rook );
235                      Xor( to, BB_W_RD );       break;
236         }
237       Xor( to, BB_WOCCUPY );
238       XorFile( to, OCCUPIED_FILE );
239       XorDiag2( to, OCCUPIED_DIAG2 );
240       XorDiag1( to, OCCUPIED_DIAG1 );
241     }
242   else {
243     const int ipiece_move = (int)I2PieceMove(move);
244     const int ipiece_cap  = (int)UToCap(move);
245     const int is_promote  = (int)I2IsPromote(move);
246     bitboard_t bb_set_clear;
247
248     BBOr( bb_set_clear, abb_mask[from], abb_mask[to] );
249     SetClear( BB_WOCCUPY );
250     BOARD[from] = empty;
251
252     if ( is_promote) switch( ipiece_move )
253       {
254       case pawn:   NocapProW( PAWN, PRO_PAWN, pawn, pro_pawn );
255                    Xor( to, BB_WPAWN_ATK );
256                    Xor( to, BB_WTGOLD );                           break;
257       case lance:  NocapProW( LANCE, PRO_LANCE, lance, pro_lance );
258                    Xor( to, BB_WTGOLD );                           break;
259       case knight: NocapProW( KNIGHT, PRO_KNIGHT, knight, pro_knight );
260                    Xor( to, BB_WTGOLD );                           break;
261       case silver: NocapProW( SILVER, PRO_SILVER, silver, pro_silver );
262                    Xor( to, BB_WTGOLD );                           break;
263       case bishop: NocapProW( BISHOP, HORSE, bishop, horse );
264                    Xor( to, BB_W_HDK );
265                    SetClear( BB_W_BH );                              break;
266       default:     NocapProW( ROOK, DRAGON, rook, dragon);
267                    Xor( to, BB_W_HDK );
268                    SetClear( BB_W_RD );                              break;
269       }
270     else switch ( ipiece_move )
271       {
272       case pawn:       NocapNoproW( PAWN, pawn );
273                        Xor( to+nfile, BB_WPAWN_ATK );
274                        Xor( to,       BB_WPAWN_ATK );     break;
275       case lance:      NocapNoproW( LANCE,     lance);      break;
276       case knight:     NocapNoproW( KNIGHT,    knight);     break;
277       case silver:     NocapNoproW( SILVER,    silver);     break;
278       case gold:       NocapNoproW( GOLD,      gold);
279                        SetClear( BB_WTGOLD );             break;
280       case bishop:     NocapNoproW( BISHOP,    bishop);
281                        SetClear( BB_W_BH );                break;
282       case rook:       NocapNoproW( ROOK,      rook);
283                        SetClear( BB_W_RD );                break;
284       case king:       HASH_KEY    ^= w_king_rand[to] ^ w_king_rand[from];
285                        BOARD[to]  = - king;
286                        SQ_WKING   = (char)to;
287                        SetClear( BB_W_HDK );               break;
288       case pro_pawn:   NocapNoproW( PRO_PAWN,   pro_pawn);
289                        SetClear( BB_WTGOLD );             break;
290       case pro_lance:  NocapNoproW( PRO_LANCE,  pro_lance);
291                        SetClear( BB_WTGOLD );             break;
292       case pro_knight: NocapNoproW( PRO_KNIGHT, pro_knight);
293                        SetClear( BB_WTGOLD );             break;
294       case pro_silver: NocapNoproW( PRO_SILVER, pro_silver);
295                        SetClear( BB_WTGOLD );             break;
296       case horse:      NocapNoproW( HORSE, horse );
297                        SetClear( BB_W_HDK );
298                        SetClear( BB_W_BH );                break;
299       default:         NocapNoproW( DRAGON, dragon );
300                        SetClear( BB_W_HDK );
301                        SetClear( BB_W_RD );                break;
302       }
303
304     if ( ipiece_cap )
305       {
306         switch( ipiece_cap )
307           {
308           case pawn:       CapB( PAWN, pawn, pawn );
309                            Xor( to-nfile, BB_BPAWN_ATK );           break;
310           case lance:      CapB( LANCE,  lance,  lance );           break;
311           case knight:     CapB( KNIGHT, knight, knight );          break;
312           case silver:     CapB( SILVER, silver, silver );          break;
313           case gold:       CapB( GOLD,   gold,   gold );
314                            Xor( to, BB_BTGOLD );                   break;
315           case bishop:     CapB( BISHOP, bishop, bishop );
316                            Xor( to, BB_B_BH );                      break;
317           case rook:       CapB( ROOK, rook, rook );
318                            Xor( to, BB_B_RD );                      break;
319           case pro_pawn:   CapB( PRO_PAWN, pawn, pro_pawn );
320                            Xor( to, BB_BTGOLD );                   break;
321           case pro_lance:  CapB( PRO_LANCE, lance, pro_lance );
322                            Xor( to, BB_BTGOLD );                   break;
323           case pro_knight: CapB( PRO_KNIGHT, knight, pro_knight );
324                            Xor( to, BB_BTGOLD );                   break;
325           case pro_silver: CapB( PRO_SILVER, silver, pro_silver );
326                            Xor( to, BB_BTGOLD );                   break;
327           case horse:      CapB( HORSE, bishop, horse );
328                            Xor( to, BB_B_HDK );
329                            Xor( to, BB_B_BH );                      break;
330           default:         CapB( DRAGON, rook, dragon );
331                            Xor( to, BB_B_HDK );
332                            Xor( to, BB_B_RD );                      break;
333           }
334         Xor( to, BB_BOCCUPY );
335         XorFile( from, OCCUPIED_FILE );
336         XorDiag1( from, OCCUPIED_DIAG1 );
337         XorDiag2( from, OCCUPIED_DIAG2 );
338       }
339     else {
340       SetClearFile( from, to, OCCUPIED_FILE );
341       SetClearDiag1( from, to, OCCUPIED_DIAG1 );
342       SetClearDiag2( from, to, OCCUPIED_DIAG2 );
343     }
344   }
345
346   assert( exam_bb( ptree ) );
347 }
348
349 #undef DropB
350 #undef DropW
351 #undef CapB
352 #undef CapW
353 #undef NocapProB
354 #undef NocapProW
355 #undef NocapNoproB
356 #undef NocapNoproW
357
358 /*
359  * flag_detect_hang
360  * flag_rep
361  * flag_time
362  * flag_nomake_move
363  * flag_history
364  * flag_rejections
365  */
366 int
367 make_move_root( tree_t * restrict ptree, unsigned int move, int flag )
368 {
369   int check, drawn, iret, i, n;
370
371   ptree->save_material[0] = (short)MATERIAL;
372   MakeMove( root_turn, move, 1 );
373
374   /* detect hang-king */
375   if ( ( flag & flag_detect_hang ) && InCheck(root_turn) )
376     {
377       str_error = str_king_hang;
378       UnMakeMove( root_turn, move, 1 );
379       return -2;
380     }
381
382   drawn = 0;
383   check = InCheck( Flip(root_turn) );
384   ptree->move_last[1]  = ptree->move_last[0];
385   if ( check )
386     {
387       ptree->nsuc_check[2] = (unsigned char)( ptree->nsuc_check[0] + 1U );
388     }
389   else { ptree->nsuc_check[2] = 0; }
390
391   /* detect repetitions */
392   if ( flag & flag_rep )
393     {
394       switch ( detect_repetition( ptree, 2, Flip(root_turn), 3 ) )
395         {
396         case perpetual_check:
397           str_error = str_perpet_check;
398           UnMakeMove( root_turn, move, 1 );
399           return -2;
400       
401         case four_fold_rep:
402           drawn = 1;
403           break;
404         }
405     }
406
407   /* return, since all of rule-checks were done */
408   if ( flag & flag_nomake_move )
409     {
410       UnMakeMove( root_turn, move, 1 );
411       return drawn ? 2 : 1;
412     }
413
414   if ( drawn ) { game_status |= flag_drawn; }
415
416   /* renovate time */
417   if ( flag & flag_time )
418     {
419       iret = renovate_time( root_turn );
420       if ( iret < 0 ) { return iret; }
421     }
422
423   root_turn = Flip( root_turn );
424   move_list[move_ptr++] = move; // [HGM] undo: remember all moves played in root
425
426   /* detect checkmate */
427   if ( check && is_mate( ptree, 1 ) ) { game_status |= flag_mated; }
428
429   /* save history */
430   if ( flag & flag_history )
431     {
432       /* save history for book learning */
433       if ( record_game.moves < HASH_REG_HIST_LEN )
434         {
435           history_book_learn[ record_game.moves ].move_played = move;
436           history_book_learn[ record_game.moves ].hand_played
437             = ptree->rep_hand_list[ root_nrep ];
438           history_book_learn[ record_game.moves ].key_played
439             = (unsigned int)ptree->rep_board_list[ root_nrep ];
440         }
441
442       out_CSA( ptree, &record_game, move );
443     }
444
445   /* add rejections */
446   if ( flag & flag_rejections ) { add_rejections_root( ptree, move ); }
447
448   /* renew repetition table */
449   n = root_nrep;
450   if ( n >= REP_HIST_LEN - PLY_MAX -1 )
451     {
452       for ( i = 0; i < n; i++ )
453         {
454           ptree->rep_board_list[i] = ptree->rep_board_list[i+1];
455           ptree->rep_hand_list[i]  = ptree->rep_hand_list[i+1];
456         }
457     }
458   else { root_nrep++; }
459
460   ptree->nsuc_check[PLY_MAX] = ptree->nsuc_check[0];
461   ptree->nsuc_check[0]       = ptree->nsuc_check[1];
462   ptree->nsuc_check[1]       = ptree->nsuc_check[2];
463
464   /* renovate pv */
465   last_root_value_save = last_root_value;
466   last_pv_save         = last_pv;
467   if ( last_pv.a[1] == move && last_pv.length >= 2 )
468     {
469       if ( last_pv.depth )
470         {
471 #if PLY_INC == EXT_CHECK
472           if ( ! check )
473 #endif
474             last_pv.depth--;
475         }
476       last_pv.length--;
477       memmove( &(last_pv.a[1]), &(last_pv.a[2]),
478                last_pv.length * sizeof( unsigned int ) );
479     }
480   else {
481     last_pv.a[0]    = 0;
482     last_pv.a[1]    = 0;
483     last_pv.depth   = 0;
484     last_pv.length  = 0;
485     last_root_value = 0;
486   }
487
488   return 1;
489 }
490
491
492 void
493 unmake_move_root( tree_t * restrict ptree, unsigned int move )
494 {
495   last_root_value = last_root_value_save;
496   last_pv         = last_pv_save;
497
498   ptree->nsuc_check[1] = ptree->nsuc_check[0];
499   ptree->nsuc_check[0] = ptree->nsuc_check[PLY_MAX];
500   
501   root_nrep   -= 1;
502   game_status &= ~( flag_drawn | flag_mated );
503   root_turn   = Flip(root_turn);
504   move_ptr--; // [HGM] undo: clip last move off game history
505
506   ptree->save_material[1]      = ptree->save_material[0];
507   UnMakeMove( root_turn, move, 1 );
508
509   sub_rejections_root( ptree, move );
510 }