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