Implement undo command
[bonanza.git] / unmake.c
1 #include <assert.h>
2 #include "shogi.h"
3
4
5 #define CapW( PIECE, piece, pro_piece )  Xor( to, BB_W ## PIECE );           \
6                                          HAND_B      -= flag_hand_ ## piece; \
7                                          BOARD[to]  = -pro_piece
8
9 #define CapB( PIECE, piece, pro_piece )  Xor( to, BB_B ## PIECE );           \
10                                          HAND_W      -= flag_hand_ ## piece; \
11                                          BOARD[to]  = pro_piece
12
13 #define NocapNopro( PIECE, piece )  SetClear( BB_ ## PIECE ); \
14                                     BOARD[from] = piece 
15
16 #define NocapPro( PIECE , PRO_PIECE, piece )  Xor( from, BB_ ## PIECE );     \
17                                               Xor( to,   BB_ ## PRO_PIECE ); \
18                                               BOARD[from] = piece
19
20
21 void
22 unmake_move_b( tree_t * restrict ptree, unsigned int move, int ply )
23 {
24   int from = (int)I2From(move);
25   int to   = (int)I2To(move);
26   int nrep = root_nrep + ply - 1;
27
28   HASH_KEY = ptree->rep_board_list[nrep];
29   MATERIAL = ptree->save_material[ply];
30
31   if ( from >= nsquare )
32     {
33       switch( From2Drop(from) )
34         {
35         case pawn:    Xor( to, BB_BPAWN );
36                       Xor( to-nfile, BB_BPAWN_ATK );
37                       HAND_B += flag_hand_pawn;     break;
38         case lance:   Xor( to, BB_BLANCE );
39                       HAND_B += flag_hand_lance;    break;
40         case knight:  Xor( to, BB_BKNIGHT );
41                       HAND_B += flag_hand_knight;   break;
42         case silver:  Xor( to, BB_BSILVER );
43                       HAND_B += flag_hand_silver;   break;
44         case gold:    Xor( to, BB_BGOLD );
45                       Xor( to, BB_BTGOLD );
46                       HAND_B += flag_hand_gold;     break;
47         case bishop:  Xor( to, BB_BBISHOP );
48                       Xor( to, BB_B_BH );
49                       HAND_B += flag_hand_bishop;   break;
50         default:      assert( From2Drop(from) == rook );
51                       Xor( to, BB_BROOK );
52                       Xor( to, BB_B_RD );
53                       HAND_B += flag_hand_rook;  break;
54         }
55
56       BOARD[to] = empty;
57       Xor( to, BB_BOCCUPY );
58       XorFile( to, OCCUPIED_FILE );
59       XorDiag2( to, OCCUPIED_DIAG2 );
60       XorDiag1( to, OCCUPIED_DIAG1 );
61     }
62   else {
63     const int ipiece_move = (int)I2PieceMove(move);
64     const int ipiece_cap  = (int)UToCap(move);
65     const int is_promote  = (int)I2IsPromote(move);
66     bitboard_t bb_set_clear;
67
68     BBOr( bb_set_clear, abb_mask[from], abb_mask[to] );
69     SetClear( BB_BOCCUPY );
70
71     if ( is_promote ) switch( ipiece_move )
72       {
73       case pawn:    NocapPro( BPAWN, BPRO_PAWN, pawn );
74                     Xor( to, BB_BPAWN_ATK );
75                     Xor( to, BB_BTGOLD );                        break;
76       case lance:   NocapPro( BLANCE,  BPRO_LANCE, lance );
77                     Xor( to, BB_BTGOLD );                        break;
78       case knight:  NocapPro( BKNIGHT, BPRO_KNIGHT, knight );
79                     Xor( to, BB_BTGOLD );                        break;
80       case silver:  NocapPro( BSILVER, BPRO_SILVER, silver );
81                     Xor( to, BB_BTGOLD );                        break;
82       case bishop:  NocapPro( BBISHOP, BHORSE, bishop );
83                     Xor( to, BB_B_HDK );
84                     SetClear( BB_B_BH );                         break;
85       default:      assert( ipiece_move == rook );
86                     NocapPro( BROOK, BDRAGON, rook );
87                     Xor( to, BB_B_HDK );
88                     SetClear( BB_B_RD );                         break;
89       }
90     else switch ( ipiece_move )
91       {
92       case pawn:        NocapNopro( BPAWN, pawn );
93                         Xor( to-nfile, BB_BPAWN_ATK );
94                         Xor( to,       BB_BPAWN_ATK );          break;
95       case lance:       NocapNopro( BLANCE,  lance );           break;
96       case knight:      NocapNopro( BKNIGHT, knight );          break;
97       case silver:      NocapNopro( BSILVER, silver );          break;
98       case gold:        NocapNopro( BGOLD, gold );
99                         SetClear( BB_BTGOLD );                  break;
100       case bishop:      NocapNopro( BBISHOP, bishop );
101                         SetClear( BB_B_BH );                    break;
102       case rook:        NocapNopro( BROOK, rook);
103                         SetClear( BB_B_RD );                    break;
104       case king:        BOARD[from] = king;
105                         SQ_BKING    = (char)from;
106                         SetClear( BB_B_HDK );                   break;
107       case pro_pawn:    NocapNopro( BPRO_PAWN, pro_pawn );
108                         SetClear( BB_BTGOLD );                  break;
109       case pro_lance:   NocapNopro( BPRO_LANCE,  pro_lance );
110                         SetClear( BB_BTGOLD );                  break;
111       case pro_knight:  NocapNopro( BPRO_KNIGHT, pro_knight );
112                         SetClear( BB_BTGOLD );                  break;
113       case pro_silver:  NocapNopro( BPRO_SILVER, pro_silver );
114                         SetClear( BB_BTGOLD );                  break;
115       case horse:       NocapNopro( BHORSE, horse );
116                         SetClear( BB_B_HDK );
117                         SetClear( BB_B_BH );                    break;
118       default:          assert( ipiece_move == dragon );
119                         NocapNopro( BDRAGON, dragon );
120                         SetClear( BB_B_HDK );
121                         SetClear( BB_B_RD );                    break;
122       }
123
124     if ( ipiece_cap )
125       {
126         switch( ipiece_cap )
127           {
128           case pawn:        CapW( PAWN,       pawn,   pawn );
129                             Xor( to+nfile, BB_WPAWN_ATK );        break;
130           case lance:       CapW( LANCE,      lance,  lance);     break;
131           case knight:      CapW( KNIGHT,     knight, knight);    break;
132           case silver:      CapW( SILVER,     silver, silver);    break;
133           case gold:        CapW( GOLD,       gold,   gold);
134                             Xor( to, BB_WTGOLD );                 break;
135           case bishop:      CapW( BISHOP,     bishop, bishop);
136                             Xor( to, BB_W_BH );                   break;
137           case rook:        CapW( ROOK,       rook,   rook);
138                             Xor( to, BB_W_RD );                   break;
139           case pro_pawn:    CapW( PRO_PAWN,   pawn,   pro_pawn);
140                             Xor( to, BB_WTGOLD );                 break;
141           case pro_lance:   CapW( PRO_LANCE,  lance,  pro_lance);
142                             Xor( to, BB_WTGOLD );                 break;
143           case pro_knight:  CapW( PRO_KNIGHT, knight, pro_knight);
144                             Xor( to, BB_WTGOLD );                 break;
145           case pro_silver:  CapW(PRO_SILVER, silver, pro_silver);
146                             Xor( to, BB_WTGOLD );                 break;
147           case horse:       CapW(HORSE,     bishop, horse);
148                             Xor( to, BB_W_HDK );
149                             Xor( to, BB_W_BH );                   break;
150           default:          assert( ipiece_cap == dragon );
151                             CapW(DRAGON,    rook,   dragon);
152                             Xor( to, BB_W_HDK );
153                             Xor( to, BB_W_RD );                   break;
154           }
155       Xor( to, BB_WOCCUPY );
156       XorFile( from, OCCUPIED_FILE );
157       XorDiag1( from, OCCUPIED_DIAG1 );
158       XorDiag2( from, OCCUPIED_DIAG2 );
159       }
160     else {
161       BOARD[to] = empty;
162       SetClearFile( from, to, OCCUPIED_FILE );
163       SetClearDiag1( from, to, OCCUPIED_DIAG1 );
164       SetClearDiag2( from, to, OCCUPIED_DIAG2 );
165     }
166   }
167
168   assert( exam_bb( ptree ) );
169 }
170
171
172 void
173 unmake_move_w( tree_t * restrict ptree, unsigned int move, int ply )
174 {
175   int from = (int)I2From(move);
176   int to   = (int)I2To(move);
177   int nrep = root_nrep + ply - 1;
178
179   HASH_KEY = ptree->rep_board_list[nrep];
180   MATERIAL = ptree->save_material[ply];
181
182   if ( from >= nsquare )
183     {
184       switch( From2Drop(from) )
185         {
186         case pawn:    Xor( to, BB_WPAWN );
187                       Xor( to+nfile, BB_WPAWN_ATK );
188                       HAND_W += flag_hand_pawn;    break;
189         case lance:   Xor( to, BB_WLANCE );
190                       HAND_W += flag_hand_lance;   break;
191         case knight:  Xor( to, BB_WKNIGHT );
192                       HAND_W += flag_hand_knight;  break;
193         case silver:  Xor( to, BB_WSILVER );
194                       HAND_W += flag_hand_silver;  break;
195         case gold:    Xor( to, BB_WGOLD );
196                       Xor( to, BB_WTGOLD );
197                       HAND_W += flag_hand_gold;    break;
198         case bishop:  Xor( to, BB_WBISHOP );
199                       Xor( to, BB_W_BH );
200                       HAND_W += flag_hand_bishop;  break;
201         default:      assert( From2Drop(from) == rook );
202                       Xor( to, BB_WROOK );
203                       Xor( to, BB_W_RD );
204                       HAND_W += flag_hand_rook;    break;
205         }
206
207       BOARD[to] = empty;
208       Xor( to, BB_WOCCUPY );
209       XorFile( to, OCCUPIED_FILE );
210       XorDiag2( to, OCCUPIED_DIAG2 );
211       XorDiag1( to, OCCUPIED_DIAG1 );
212     }
213   else {
214     const int ipiece_move = (int)I2PieceMove(move);
215     const int ipiece_cap  = (int)UToCap(move);
216     const int is_promote  = (int)I2IsPromote(move);
217     bitboard_t bb_set_clear;
218
219     BBOr( bb_set_clear, abb_mask[from], abb_mask[to] );
220     SetClear( BB_WOCCUPY );
221
222     if ( is_promote ) switch( ipiece_move )
223       {
224       case pawn:    NocapPro( WPAWN, WPRO_PAWN, -pawn );
225                     Xor( to, BB_WPAWN_ATK );
226                     Xor( to, BB_WTGOLD );                        break;
227       case lance:   NocapPro( WLANCE, WPRO_LANCE, -lance );
228                     Xor( to, BB_WTGOLD );                        break;
229       case knight:  NocapPro( WKNIGHT, WPRO_KNIGHT, -knight );
230                     Xor( to, BB_WTGOLD );                        break;
231       case silver:  NocapPro( WSILVER, WPRO_SILVER, -silver );
232                     Xor( to, BB_WTGOLD );                        break;
233       case bishop:  NocapPro( WBISHOP, WHORSE, -bishop );
234                     Xor( to, BB_W_HDK );
235                     SetClear( BB_W_BH );                         break;
236       default:      assert( ipiece_move == rook );
237                     NocapPro( WROOK, WDRAGON, -rook );
238                     Xor( to, BB_W_HDK );
239                     SetClear( BB_W_RD );                         break;
240       }
241     else switch ( ipiece_move )
242       {
243       case pawn:        NocapNopro( WPAWN, -pawn );
244                         Xor( to+nfile, BB_WPAWN_ATK );
245                         Xor( to,       BB_WPAWN_ATK );          break;
246       case lance:       NocapNopro( WLANCE,  -lance );          break;
247       case knight:      NocapNopro( WKNIGHT, -knight );         break;
248       case silver:      NocapNopro( WSILVER, -silver );         break;
249       case gold:        NocapNopro( WGOLD,   -gold );
250                         SetClear( BB_WTGOLD );                  break;
251       case bishop:      NocapNopro( WBISHOP, -bishop );
252                         SetClear( BB_W_BH );                    break;
253       case rook:        NocapNopro( WROOK, -rook );
254                         SetClear( BB_W_RD );                    break;
255       case king:        BOARD[from] = -king;
256                         SQ_WKING    = (char)from;
257                         SetClear( BB_W_HDK );                   break;
258       case pro_pawn:    NocapNopro( WPRO_PAWN,  -pro_pawn );
259                         SetClear( BB_WTGOLD );                  break;
260       case pro_lance:   NocapNopro( WPRO_LANCE, -pro_lance );
261                         SetClear( BB_WTGOLD );                  break;
262       case pro_knight:  NocapNopro( WPRO_KNIGHT,-pro_knight );
263                         SetClear( BB_WTGOLD );                  break;
264       case pro_silver:  NocapNopro( WPRO_SILVER, -pro_silver );
265                         SetClear( BB_WTGOLD );                  break;
266       case horse:       NocapNopro( WHORSE, -horse );
267                         SetClear( BB_W_HDK );
268                         SetClear( BB_W_BH );                    break;
269       default:          assert( ipiece_move == dragon );
270                         NocapNopro( WDRAGON, -dragon );
271                         SetClear( BB_W_HDK );
272                         SetClear( BB_W_RD );                    break;
273       }
274     
275     if ( ipiece_cap )
276       {
277         switch( ipiece_cap )
278           {
279           case pawn:        CapB( PAWN,      pawn,   pawn );
280                             Xor( to-nfile, BB_BPAWN_ATK );      break;
281           case lance:       CapB( LANCE,     lance,  lance );   break;
282           case knight:      CapB( KNIGHT,    knight, knight );  break;
283           case silver:      CapB( SILVER,    silver, silver );  break;
284           case gold:        CapB( GOLD,      gold,   gold );
285                             Xor( to, BB_BTGOLD );              break;
286           case bishop:      CapB( BISHOP,    bishop, bishop );
287                             Xor( to, BB_B_BH );                 break;
288           case rook:        CapB( ROOK,      rook,   rook );
289                             Xor( to, BB_B_RD );                 break;
290           case pro_pawn:    CapB( PRO_PAWN,   pawn,   pro_pawn );
291                             Xor( to, BB_BTGOLD );              break;
292           case pro_lance:   CapB( PRO_LANCE,  lance,  pro_lance );
293                             Xor( to, BB_BTGOLD );              break;
294           case pro_knight:  CapB( PRO_KNIGHT, knight, pro_knight );
295                             Xor( to, BB_BTGOLD );              break;
296           case pro_silver:  CapB( PRO_SILVER, silver, pro_silver );
297                             Xor( to, BB_BTGOLD );              break;
298           case horse:       CapB( HORSE,     bishop, horse );
299                             Xor( to, BB_B_HDK );
300                             Xor( to, BB_B_BH );                 break;
301           default:          assert( ipiece_cap == dragon );
302                             CapB( DRAGON,    rook,   dragon);
303                             Xor( to, BB_B_HDK );
304                             Xor( to, BB_B_RD );                 break;
305           }
306         Xor( to, BB_BOCCUPY );
307         XorFile( from, OCCUPIED_FILE );
308         XorDiag1( from, OCCUPIED_DIAG1 );
309         XorDiag2( from, OCCUPIED_DIAG2 );
310       }
311     else {
312       BOARD[to] = empty;
313       SetClearFile( from, to, OCCUPIED_FILE );
314       SetClearDiag1( from, to, OCCUPIED_DIAG1 );
315       SetClearDiag2( from, to, OCCUPIED_DIAG2 );
316     }
317   }
318
319   assert( exam_bb( ptree ) );
320 }
321
322
323 #undef CapW
324 #undef CapB
325 #undef NocapNopro
326 #undef NocapPro