1 /*
2 * executing and unexecuting generated moves
3 */
4
5 #include "phalanx.h"
6
7
8 #undef DEBUG_MLIST
9 #ifdef DEBUG_MLIST
checklist(tmove * m)10 int checklist(tmove *m)
11 {
12 int j;
13 int err=0;
14 int wp=0, bp=0;
15 for( j=WKP; j!=0 && wp<18; j=L[j].next )
16 { wp++; if(color(B[j])!=WHITE) err=1; }
17 for( j=A1; j!=H9; j++ ) if( color(B[j])==WHITE ) wp--;
18
19 for( j=BKP; j!=0 && bp<18; j=L[j].next )
20 { bp++; if(color(B[j])!=BLACK) err=1; }
21 for( j=A1; j!=H9; j++ ) if( color(B[j])==BLACK ) bp--;
22
23 if( wp!=0 || bp!=0 || err )
24 {
25 int x=18;
26 puts("");
27 for( j=WKP; j!=0 && x!=0; j=L[j].next )
28 { x--; if(color(B[j])!=WHITE) printf("!"); printf("%i,",j); }
29 puts("");
30 x=18;
31 for( j=BKP; j!=0 && x!=0; j=L[j].next )
32 { x--; if(color(B[j])!=BLACK) printf("!"); printf("%i,",j); }
33 puts("");
34 printboard(NULL);
35 printf("wp=%i, bp=%i\n",wp,bp);
36 for(j=0;j!=Counter;j++) printm(G[j].m,NULL);
37 puts(""); if( m!=NULL) printm(*m,NULL);
38 getchar();
39 return 1;
40 }
41 return 0;
42 }
43 #endif
44
45
46
47 #define update_hash(p,s) { G[Counter].hashboard ^= H[ HP[p] ][ HS[s] ]; }
48
49
50
do_move(register tmove * m)51 void do_move(register tmove * m)
52 {
53
54 G[Counter].m = *m;
55 Counter++;
56 G[Counter].castling = G[Counter-1].castling;
57 G[Counter].rule50 = G[Counter-1].rule50 + 1;
58 G[Counter].hashboard = HASH_COLOR ^ G[Counter-1].hashboard;
59 G[Counter].mtrl = G[Counter-1].xmtrl;
60 G[Counter].xmtrl = G[Counter-1].mtrl;
61 Ply++;
62
63 switch(m->special)
64 {
65 case 0: /* most of the moves */
66
67 update_hash( m->in1, m->from );
68 update_hash( m->in2a, m->to );
69 if( m->in2 != 0 ) /* capture */
70 {
71 update_hash( m->in2, m->to );
72 G[Counter].mtrl -= Values[ m->in2 >> 4 ];
73 G[Counter].rule50 = 0;
74
75 /* remove captured piece from the list */
76 L[ L[m->to].prev ].next = L[m->to].next;
77 L[ L[m->to].next ].prev = L[m->to].prev;
78 } else
79 if( piece(m->in1) == PAWN ) G[Counter].rule50 = 0;
80
81 /* update piece list */
82 L[m->to] = L[m->from];
83 L[ L[m->to].prev ].next = L[ L[m->to].next ].prev = m->to;
84
85 if( m->in2a != m->in1 ) /* pawn promotion */
86 G[Counter].xmtrl += Values[ m->in2a >> 4 ] - P_VALUE;
87
88 B[m->from] = 0;
89 B[m->to] = m->in2a;
90
91 {
92 static unsigned char cb_[80] =
93 {
94 0, WLONG, 0, 0, 0, (WSHORT|WLONG), 0, 0, WSHORT, 0,
95 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
96 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
97 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
98 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
99 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
100 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
101 0, BLONG, 0, 0, 0, (BSHORT|BLONG), 0, 0, BSHORT, 0
102 }; static unsigned char * cb = cb_-20;
103
104 G[Counter].castling |= cb[m->from] | cb[m->to];
105 }
106
107 break;
108
109 case SHORT_CASTLING:
110 if( Color == WHITE )
111 {
112 B[E1]=0; B[F1]=WR; B[G1]=WK; B[H1]=0;
113 G[Counter].castling |= ( WSHORT | WLONG );
114 update_hash( WK, E1 );
115 update_hash( WK, G1 );
116 update_hash( WR, H1 );
117 update_hash( WR, F1 );
118 L[G1] = L[E1]; WKP = L[L[G1].next].prev = G1;
119 L[F1] = L[H1]; L[L[F1].prev].next = L[L[F1].next].prev = F1;
120 }
121 else
122 {
123 B[E8]=0; B[F8]=BR; B[G8]=BK; B[H8]=0;
124 G[Counter].castling |= ( BSHORT | BLONG );
125 update_hash( BK, E8 );
126 update_hash( BK, G8 );
127 update_hash( BR, H8 );
128 update_hash( BR, F8 );
129 L[G8] = L[E8]; BKP = L[L[G8].next].prev = G8;
130 L[F8] = L[H8]; L[L[F8].prev].next = L[L[F8].next].prev = F8;
131 }
132 break;
133 case LONG_CASTLING:
134 if( Color == WHITE )
135 {
136 B[A1]=0; B[C1]=WK; B[D1]=WR; B[E1]=0;
137 G[Counter].castling |= ( WSHORT | WLONG );
138 update_hash( WK, E1 );
139 update_hash( WK, C1 );
140 update_hash( WR, A1 );
141 update_hash( WR, D1 );
142 L[C1] = L[E1]; WKP = L[L[C1].next].prev = C1;
143 L[D1] = L[A1]; L[L[D1].prev].next = L[L[D1].next].prev = D1;
144 }
145 else
146 {
147 B[A8]=0; B[C8]=BK; B[D8]=BR; B[E8]=0;
148 G[Counter].castling |= ( BSHORT | BLONG );
149 update_hash( BK, E8 );
150 update_hash( BK, C8 );
151 update_hash( BR, A8 );
152 update_hash( BR, D8 );
153 L[C8] = L[E8]; BKP = L[L[C8].next].prev = C8;
154 L[D8] = L[A8]; L[L[D8].prev].next = L[L[D8].next].prev = D8;
155 }
156 break;
157 default: /* en passant pawn capture */
158
159 update_hash( m->in1, m->from );
160 update_hash( m->in2a, m->to );
161 update_hash( B[m->special], m->special );
162
163 B[m->from] = 0;
164 B[m->to] = m->in2a;
165 B[m->special] = 0; /* captured pawn */
166
167 /* update piece list */
168 L[m->to] = L[m->from];
169 L[ L[m->to].prev ].next = L[ L[m->to].next ].prev = m->to;
170 L[L[m->special].next].prev = L[m->special].prev;
171 L[L[m->special].prev].next = L[m->special].next;
172
173 G[Counter].mtrl -= P_VALUE;
174 G[Counter].rule50 = 0; /* this is an irreversible move */
175 }
176
177 Color = enemy(Color);
178 Depth -= m->dch;
179
180 #ifdef DEBUG_MLIST
181 checklist(m);
182 #endif
183
184 }
185
186
187
undo_move(register tmove * m)188 void undo_move(register tmove * m)
189 {
190
191 Color = enemy(Color);
192 Depth += m->dch;
193 Ply--; Counter--;
194
195 switch(m->special)
196 {
197 case 0: /* most of the moves */
198 B[m->from] = m->in1;
199 B[m->to] = m->in2;
200
201 /* update piece list */
202 L[m->from] = L[m->to];
203 L[ L[m->from].prev ].next = L[ L[m->from].next ].prev = m->from;
204 if( m->in2 != 0 ) /* return captured piece to the list */
205 {
206 if( color(m->in2) == WHITE )
207 {
208 L[m->to].next = L[WKP].next;
209 L[m->to].prev = WKP;
210 L[L[WKP].next].prev = m->to;
211 L[WKP].next = m->to;
212 }
213 else
214 {
215 L[m->to].next = L[BKP].next;
216 L[m->to].prev = BKP;
217 L[L[BKP].next].prev = m->to;
218 L[BKP].next = m->to;
219 }
220 }
221 break;
222 case SHORT_CASTLING:
223 if( Color == WHITE )
224 {
225 B[E1]=WK; B[F1]=0; B[G1]=0; B[H1]=WR;
226 L[E1] = L[G1]; WKP = L[L[E1].next].prev = E1;
227 L[H1] = L[F1]; L[L[H1].prev].next = L[L[H1].next].prev = H1;
228 }
229 else
230 {
231 B[E8]=BK; B[F8]=0; B[G8]=0; B[H8]=BR;
232 L[E8] = L[G8]; BKP = L[L[E8].next].prev = E8;
233 L[H8] = L[F8]; L[L[H8].prev].next = L[L[H8].next].prev = H8;
234 }
235 break;
236 case LONG_CASTLING:
237 if( Color == WHITE )
238 {
239 B[A1]=WR; B[C1]=0; B[D1]=0; B[E1]=WK;
240 L[E1] = L[C1]; WKP = L[L[E1].next].prev = E1;
241 L[A1] = L[D1]; L[L[A1].prev].next = L[L[A1].next].prev = A1;
242 }
243 else
244 {
245 B[A8]=BR; B[C8]=0; B[D8]=0; B[E8]=BK;
246 L[E8] = L[C8]; BKP = L[L[E8].next].prev = E8;
247 L[A8] = L[D8]; L[L[A8].prev].next = L[L[A8].next].prev = A8;
248 }
249 break;
250 default: /* en passant pawn capture */
251 B[m->to] = 0;
252 L[m->from] = L[m->to];
253 L[ L[m->from].prev ].next = L[ L[m->from].next ].prev = m->from;
254 if( Color == WHITE )
255 {
256 B[m->from] = WP;
257 B[m->special] = BP; /* captured pawn */
258 L[m->special].next = L[BKP].next;
259 L[m->special].prev = BKP;
260 L[L[BKP].next].prev = m->special;
261 L[BKP].next = m->special;
262 }
263 else
264 {
265 B[m->from] = BP;
266 B[m->special] = WP; /* captured pawn */
267 L[m->special].next = L[WKP].next;
268 L[m->special].prev = WKP;
269 L[L[WKP].next].prev = m->special;
270 L[WKP].next = m->special;
271 }
272 }
273
274 #ifdef DEBUG_MLIST
275 checklist(m);
276 #endif
277
278 }
279
280
281
282 #ifdef ETTC
283 /**
284 *** Doing and undoing only hash keys. To be used for ETC
285 *** (enhanced transpostion cutoffs); see evaluate.c
286 **/
287
do_hash(register tmove * m)288 void do_hash(register tmove * m)
289 {
290
291 Counter++;
292 G[Counter].hashboard = HASH_COLOR ^ G[Counter-1].hashboard;
293
294 switch(m->special)
295 {
296 case 0: /* most of the moves */
297
298 update_hash( m->in1, m->from );
299 update_hash( m->in2a, m->to );
300 if( m->in2 != 0 ) /* capture */
301 update_hash( m->in2, m->to );
302
303 break;
304
305 case SHORT_CASTLING:
306 if( Color == WHITE )
307 {
308 update_hash( WK, E1 );
309 update_hash( WK, G1 );
310 update_hash( WR, H1 );
311 update_hash( WR, F1 );
312 }
313 else
314 {
315 update_hash( BK, E8 );
316 update_hash( BK, G8 );
317 update_hash( BR, H8 );
318 update_hash( BR, F8 );
319 }
320 break;
321 case LONG_CASTLING:
322 if( Color == WHITE )
323 {
324 update_hash( WK, E1 );
325 update_hash( WK, C1 );
326 update_hash( WR, A1 );
327 update_hash( WR, D1 );
328 }
329 else
330 {
331 update_hash( BK, E8 );
332 update_hash( BK, C8 );
333 update_hash( BR, A8 );
334 update_hash( BR, D8 );
335 }
336 break;
337 default: /* en passant pawn capture */
338
339 update_hash( m->in1, m->from );
340 update_hash( m->in2a, m->to );
341 update_hash( B[m->special], m->special );
342 }
343
344 Depth -= m->dch;
345
346 }
347
348
349
undo_hash(register tmove * m)350 void undo_hash(register tmove * m)
351 {
352 Depth += m->dch;
353 Counter--;
354 }
355
356 #endif /* ETTC */
357
358