1 /* this file contains all the code that keeps the board position
2    uptodate, calling eval and hash procedures to ensure that
3    the hashes and evaluation are also kept uptodate */
4 
5 #include "includes.h"
6 #include "knightcap.h"
7 
8 extern struct state *state;
9 
10 struct hashvalue_entry hash_values;
11 
init_hash_values(void)12 static inline void init_hash_values(void)
13 {
14 	static int initialised;
15 	int i, j;
16 
17 	if (initialised) return;
18 	initialised = 1;
19 
20 	memset(&hash_values, 0, sizeof(hash_values));
21 
22 	for (i=0;i<(2*KING+1);i++)
23 		if (i != KING)
24 			for (j=0;j<NUM_SQUARES;j++) {
25 				hash_values.v1[i][j] = random() & ~1;
26 				hash_values.v2[i][j] = random();
27 			}
28 }
29 
eval_piece(Position * b,PieceStruct * p)30 static void eval_piece(Position *b, PieceStruct *p)
31 {
32 	if (p->p > 0)
33 		b->w_material += mat_value(p->p);
34 	else
35 		b->b_material += mat_value(-p->p);
36 }
37 
deval_piece(Position * b,PieceStruct * p)38 static void deval_piece(Position *b, PieceStruct *p)
39 {
40 	if (p->p > 0)
41 		b->w_material -= mat_value(p->p);
42 	else
43 		b->b_material -= mat_value(-p->p);
44 }
45 
46 
remove_piece(Position * b,PieceStruct * piece)47 static inline void remove_piece(Position *b, PieceStruct *piece)
48 {
49 	int pi = (piece - b->pieces);
50 	uint32 mask = ~(1<<pi);
51 
52 	deval_piece(b, piece);
53 	remove_hash(b, piece->pos, piece->p);
54 	set_pboard(b, piece->pos, NULL);
55 	b->board[piece->pos] = 0;
56 	piece->p = 0;
57 	b->pawns7th &= mask;
58 	b->wpassed_pawn_mask &= mask;
59 	b->bpassed_pawn_mask &= mask;
60 	b->piece_mask &= mask;
61 	b->material_mask &= mask;
62 }
63 
64 
move_piece(Position * b,PieceStruct * piece,Square to)65 static inline void move_piece(Position *b, PieceStruct *piece, Square to)
66 {
67 	int pi = (piece - b->pieces);
68 	if (b->pawns7th & (1<<pi))
69 		b->pawns7th &= ~(1<<pi);
70 	remove_hash(b, piece->pos, piece->p);
71 	set_pboard(b, piece->pos, NULL);
72 	set_pboard(b, to, piece);
73 	b->board[piece->pos] = 0;
74 	b->board[to] = piece->p;
75 	piece->pos = to;
76 	add_hash(b, piece->pos, piece->p);
77 	if ((piece->p == PAWN && YPOS(to) == 6) ||
78 	    (piece->p == -PAWN && YPOS(to) == 1)) {
79 		b->pawns7th |= (1<<pi);
80 	}
81 }
82 
add_piece(Position * b,Piece p,Square to,PieceStruct * piece)83 static inline void add_piece(Position *b, Piece p, Square to,
84 			     PieceStruct *piece)
85 {
86 	int pi = (piece - b->pieces);
87 	b->board[to] = p;
88 	piece->pos = to;
89 	piece->p = p;
90 
91 	set_pboard(b, to, piece);
92 	add_hash(b, piece->pos, piece->p);
93 	eval_piece(b, piece);
94 
95 	if (is_sliding(p))
96 		b->sliding_mask |= (1<<pi);
97 
98 	if ((p == PAWN && YPOS(to) == 6) || (p == -PAWN && YPOS(to) == 1)) {
99 		b->pawns7th |= (1<<pi);
100 	}
101 
102 	if (abs(p) != PAWN)
103 		b->piece_mask |= (1<<pi);
104 	b->material_mask |= (1<<pi);
105 }
106 
107 
change_piece(Position * b,PieceStruct * piece,Piece to)108 static inline void change_piece(Position *b, PieceStruct *piece, Piece to)
109 {
110 	int pi = (piece - b->pieces);
111 	Square pos = piece->pos;
112 
113 	if (to == QUEEN && !(b->piece_mask & WQUEEN_MASK)) {
114 		remove_piece(b, piece);
115 		add_piece(b, QUEEN, pos, &(WHITEPIECES(b)[IQUEEN]));
116 	} else if (to == -QUEEN && !(b->piece_mask & BQUEEN_MASK)) {
117 		remove_piece(b, piece);
118 		add_piece(b, -QUEEN, pos, &(BLACKPIECES(b)[IQUEEN]));
119 	} else {
120 		deval_piece(b, piece);
121 		remove_hash(b, piece->pos, piece->p);
122 		b->board[piece->pos] = to;
123 		piece->p = to;
124 		add_hash(b, piece->pos, piece->p);
125 		eval_piece(b, piece);
126 		if (is_sliding(to)) {
127 			b->sliding_mask |= (1<<pi);
128 		}
129 		if (abs(to) != PAWN)
130 			b->piece_mask |= (1<<pi);
131 	}
132 }
133 
134 
check_repitition(Position * b,int repeats)135 int check_repitition(Position *b, int repeats)
136 {
137 	int i;
138 
139 	/* check for exceeding the 50 move rule */
140 	if (b->fifty_count > REPITITION_LENGTH) return 1;
141 
142 	/* and evaluate as a draw if the position has occurred before with
143 	   the same player to play */
144 	for (i=b->move_num-2;
145 	     repeats && i>=(b->move_num - b->fifty_count);
146 	     i-=2) {
147 		if (state->hash_list[i] == b->hash1)
148 			repeats--;
149 	}
150 
151 	return repeats == 0;
152 }
153 
154 
copy_position(Position * d,Position * s)155 static inline void copy_position(Position *d, Position *s)
156 {
157 	int n = (((char *)&d->dont_copy) - ((char *)d));
158 	memcpy((char *)d, (char *)s, n);
159 }
160 
161 /* execute the move on the board and update the flags and all the
162    state information
163  */
do_move_part1(Position * b,Position * oldb,Move * move)164 int do_move_part1(Position *b, Position *oldb, Move *move)
165 {
166 	Piece p1;
167 	PieceStruct *piece, *oldpiece;
168 	int complex_move = 0;
169 	static Position b1;
170 
171 	init_hash_values();
172 
173 	if (oldb == b) {
174 		b1 = (*b);
175 		oldb = &b1;
176 	} else {
177 		copy_position(b, oldb);
178 	}
179 
180 	p1 = b->board[move->from];
181 
182 	piece = get_pboard(b, move->from);
183 
184 	if (!piece || !p1) {
185 		lprintf(0,"no piece! %s\n", short_movestr(b, move));
186 		print_board(b->board);
187 		save_game("bug.game");
188 		return 0;
189 	}
190 
191 #if 0
192 	if ((b->board[move->from] > 0 && b->board[move->to] > 0) ||
193 	    (b->board[move->from] < 0 && b->board[move->to] < 0)) {
194 		lprintf(0,"own capture! %s\n", short_movestr(b, move));
195 		print_board(b->board);
196 		save_game("bug.game");
197 		return 0;
198 	}
199 
200 	if (abs(b->board[move->to]) == KING) {
201 		lprintf(0,"king capture! %s\n", short_movestr(b, move));
202 		print_board(b->board);
203 		save_game("bug.game");
204 		return 0;
205 	}
206 #endif
207 
208 	oldpiece = get_pboard(b, move->to);
209 
210 	b->last_move = (*move);
211 
212 	zero_move(&b->best_capture);
213 
214 	b->flags = oldb->flags & ~(FLAG_CHECK|FLAG_PREV_CHECK|FLAG_EVAL_DONE|FLAG_EXTENDED|FLAG_DONE_TACTICS);
215 	if (oldb->flags & FLAG_CHECK) {
216 		b->flags |= FLAG_PREV_CHECK;
217 	}
218 
219 	if (oldpiece) {
220 		remove_piece(b, oldpiece);
221 	}
222 
223 	move_piece(b, piece, move->to);
224 
225 	/* that was the easy bit - now all the messy bits */
226 
227 	/* did they take enpassent? */
228 	if (oldb->enpassent && move->to == oldb->enpassent && abs(p1) == PAWN) {
229 		if (p1 == PAWN) {
230 			oldpiece = get_pboard(b, move->to + SOUTH);
231 		} else {
232 			oldpiece = get_pboard(b, move->to + NORTH);
233 		}
234 		remove_piece(b, oldpiece);
235 		complex_move = 1;
236 	}
237 
238 	/* did they promote? */
239 	if (oldb->pawns7th) {
240 		if (p1 == PAWN && YPOS(piece->pos) == 7) {
241 			if (oldb->promotion)
242 				change_piece(b, piece, oldb->promotion);
243 			else {
244 				change_piece(b, piece, QUEEN);
245 				b->flags |= FLAG_WHITE_PROMOTE;
246 			}
247 			complex_move = 1;
248 		} else if (p1 == -PAWN && YPOS(piece->pos) == 0) {
249 			if (oldb->promotion)
250 				change_piece(b, piece, -oldb->promotion);
251 			else {
252 				change_piece(b, piece, -QUEEN);
253 				b->flags |= FLAG_BLACK_PROMOTE;
254 			}
255 			complex_move = 1;
256 		}
257 	}
258 
259 	b->promotion = 0;
260 
261 	b->hash1 ^= (oldb->enpassent<<8);
262 
263 	/* can the next player move enpassent? */
264 	if (p1 == PAWN && (move->to == move->from + 2*NORTH) &&
265 	    (oldb->topieces[move->from+NORTH] & BPAWN_MASK)) {
266 		b->enpassent = move->from + NORTH;
267 	} else if (p1 == -PAWN && (move->to == move->from + 2*SOUTH) &&
268 		   (oldb->topieces[move->from+SOUTH] & WPAWN_MASK)) {
269 		b->enpassent = move->from + SOUTH;
270 	} else {
271 		b->enpassent = 0;
272 	}
273 
274 	b->hash1 ^= (b->enpassent<<8);
275 
276 
277 	if (!(b->flags & FLAG_CAN_CASTLE))
278 		goto cant_castle;
279 
280 	b->hash1 ^= (b->flags & (FLAG_CAN_CASTLE)) << 16;
281 
282 	/* have they castled? */
283 	if (p1 == KING || p1 == -KING) {
284 		if (move->to == move->from + 2*EAST) {
285 			move_piece(b, get_pboard(b, move->from + 3*EAST),
286 				   move->from + EAST);
287 			complex_move = 1;
288 		} else if (move->to == move->from + 2*WEST) {
289 			move_piece(b, get_pboard(b, move->from + 4*WEST),
290 				   move->from + WEST);
291 			complex_move = 1;
292 		}
293 	}
294 
295 	/* have they wrecked their castling chances? There are lots of
296            ways to do it! */
297 	if (p1 == KING &&
298 	    (b->flags & (WHITE_CASTLE_LONG | WHITE_CASTLE_SHORT))) {
299 		if (move->from == E1 && (move->to == G1 || move->to == C1))
300 			b->flags |= WHITE_CASTLED;
301 		b->flags &= ~(WHITE_CASTLE_LONG | WHITE_CASTLE_SHORT);
302 	} else if (p1 == -KING &&
303 		   (b->flags & (BLACK_CASTLE_LONG | BLACK_CASTLE_SHORT))) {
304 		if (move->from == E8 && (move->to == G8 || move->to == C8))
305 			b->flags |= BLACK_CASTLED;
306 		b->flags &= ~(BLACK_CASTLE_LONG | BLACK_CASTLE_SHORT);
307 	}
308 
309 	if (p1 == ROOK) {
310 		if (move->from == A1 && (b->flags & WHITE_CASTLE_LONG)) {
311 			b->flags &= ~WHITE_CASTLE_LONG;
312 		} else if (move->from == H1 &&
313 			   (b->flags & WHITE_CASTLE_SHORT)) {
314 			b->flags &= ~WHITE_CASTLE_SHORT;
315 		}
316 	} else if (p1 == -ROOK) {
317 		if (move->from == A8 && (b->flags & BLACK_CASTLE_LONG)) {
318 			b->flags &= ~BLACK_CASTLE_LONG;
319 		} else if (move->from == H8 &&
320 			   (b->flags & BLACK_CASTLE_SHORT)) {
321 			b->flags &= ~BLACK_CASTLE_SHORT;
322 		}
323 	}
324 
325 	/* this covers rook captures which wreck castling chances */
326 	if (oldpiece) {
327 		if (move->to == A1 && (b->flags & WHITE_CASTLE_LONG)) {
328 			b->flags &= ~WHITE_CASTLE_LONG;
329 		} else if (move->to == H1 && (b->flags & WHITE_CASTLE_SHORT)) {
330 			b->flags &= ~WHITE_CASTLE_SHORT;
331 		} else if (move->to == A8 && (b->flags & BLACK_CASTLE_LONG)) {
332 			b->flags &= ~BLACK_CASTLE_LONG;
333 		} else if (move->to == H8 && (b->flags & BLACK_CASTLE_SHORT)) {
334 			b->flags &= ~BLACK_CASTLE_SHORT;
335 		}
336 	}
337 
338 	b->hash1 ^= (b->flags & (FLAG_CAN_CASTLE)) << 16;
339 
340 	if ((b->flags & FLAG_CAN_CASTLE) != (oldb->flags & FLAG_CAN_CASTLE))
341 		complex_move = 1;
342 
343  cant_castle:
344 
345 	/* update the fifty move counter */
346 	if (oldpiece || abs(p1) == PAWN)
347 		b->fifty_count = 1;
348 	else
349 		b->fifty_count = oldb->fifty_count+1;
350 
351 	state->hash_list[oldb->move_num] = oldb->hash1;
352 	state->hash_list[oldb->move_num+1] = b->hash1;
353 
354 	b->move_num = oldb->move_num+1;
355 	b->winner = oldb->winner;
356 	b->num_moves = 0;
357 	b->moves = NULL;
358 	if (oldb != &b1) {
359 		b->oldb = oldb;
360 	} else {
361 		b->oldb = NULL;
362 		complex_move = 1;
363 	}
364 
365 	/* we use the bottom bit of hash1 to indicate who is to move
366 	   in hash entries */
367 	b->hash1 ^= 1;
368 
369 	if (!complex_move) {
370 		b->flags |= FLAG_NEED_PART2;
371 		return 1;
372 	}
373 
374 	regen_moves(b);
375 	b->flags &= ~FLAG_NEED_PART2;
376 
377 	if (p1 > 0) {
378 		int bkpos = BLACKPIECES(b)[IKING].pos;
379 		int wkpos = WHITEPIECES(b)[IKING].pos;
380 		if (b->topieces[wkpos] & BLACK_MASK)
381 			return 0;
382 		if (b->topieces[bkpos] & WHITE_MASK)
383 			b->flags |= FLAG_CHECK;
384 	} else {
385 		int bkpos = BLACKPIECES(b)[IKING].pos;
386 		int wkpos = WHITEPIECES(b)[IKING].pos;
387 		if (b->topieces[bkpos] & WHITE_MASK)
388 			return 0;
389 		if (b->topieces[wkpos] & BLACK_MASK)
390 			b->flags |= FLAG_CHECK;
391 	}
392 
393 	return 1;
394 }
395 
396 
397 /* execute the move on the board and update the flags and all the
398    state information
399  */
do_move_part2(Position * b)400 int do_move_part2(Position *b)
401 {
402 	if (!(b->flags & FLAG_NEED_PART2)) return 1;
403 
404 	b->flags &= ~FLAG_NEED_PART2;
405 
406 	update_moves(b, b->oldb, &b->last_move);
407 
408 	if (blacks_move(b)) {
409 		int bkpos = BLACKPIECES(b)[IKING].pos;
410 		int wkpos = WHITEPIECES(b)[IKING].pos;
411 		if (b->topieces[wkpos] & BLACK_MASK)
412 			return 0;
413 		if (b->topieces[bkpos] & WHITE_MASK)
414 			b->flags |= FLAG_CHECK;
415 	} else {
416 		int bkpos = BLACKPIECES(b)[IKING].pos;
417 		int wkpos = WHITEPIECES(b)[IKING].pos;
418 		if (b->topieces[bkpos] & WHITE_MASK)
419 			return 0;
420 		if (b->topieces[wkpos] & BLACK_MASK)
421 			b->flags |= FLAG_CHECK;
422 	}
423 
424 	return 1;
425 }
426 
do_move(Position * b,Position * oldb,Move * move)427 int do_move(Position *b, Position *oldb, Move *move)
428 {
429 	if (!do_move_part1(b, oldb, move)) return 0;
430 
431 	return do_move_part2(b);
432 }
433 
434 
435 /* setup the usual initial position */
setup_board(Position * b)436 void setup_board(Position *b)
437 {
438 	timer_reset();
439 
440 	memset(b, 0, sizeof(*b));
441 
442 	/* all castling options are enabled */
443 	b->flags = WHITE_CASTLE_LONG | WHITE_CASTLE_SHORT |
444 		BLACK_CASTLE_LONG | BLACK_CASTLE_SHORT;
445 
446 	b->board[A1] = b->board[H1] = ROOK;
447 	b->board[B1] = b->board[G1] = KNIGHT;
448 	b->board[C1] = b->board[F1] = BISHOP;
449 	b->board[D1] = QUEEN;
450 	b->board[E1] = KING;
451 	b->board[A2] = b->board[B2] = b->board[C2] = b->board[D2] = PAWN;
452 	b->board[E2] = b->board[F2] = b->board[G2] = b->board[H2] = PAWN;
453 
454 	b->board[A8] = b->board[H8] = -ROOK;
455 	b->board[B8] = b->board[G8] = -KNIGHT;
456 	b->board[C8] = b->board[F8] = -BISHOP;
457 	b->board[D8] = -QUEEN;
458 	b->board[E8] = -KING;
459 	b->board[A7] = b->board[B7] = b->board[C7] = b->board[D7] = -PAWN;
460 	b->board[E7] = b->board[F7] = b->board[G7] = b->board[H7] = -PAWN;
461 
462 	create_pboard(b);
463 }
464 
465 
piece_comp(const void * pp1,const void * pp2)466 static int piece_comp(const void *pp1, const void *pp2)
467 {
468 	PieceStruct *p1;
469 	PieceStruct *p2;
470 	int ret;
471 
472 	p1 = (PieceStruct *)pp1;
473 	p2 = (PieceStruct *)pp2;
474 
475 	ret = abs(p2->p) - abs(p1->p);
476 	if (ret == 0)
477 		return p2->pos - p1->pos;
478 	return ret;
479 }
480 
481 
shiftup(PieceStruct * p,int loc,int * n)482 static void shiftup(PieceStruct *p, int loc, int *n)
483 {
484 	memmove(&p[loc+1], &p[loc], ((*n)-loc)*sizeof(*p));
485 	p[loc].p = 0;
486 	(*n)++;
487 }
488 
489 
490 /* this assumes the board is correct and tries to form
491    a pboard and piece list. Its done in this ugly way so that
492    KnightCap can setup any position using the same code, and
493    get the pieces in a sensible order for its bitmasks */
create_pboard(Position * b)494 int create_pboard(Position *b)
495 {
496 	int i;
497 	PieceStruct *pw = WHITEPIECES(b);
498 	PieceStruct *pb = BLACKPIECES(b);
499 	PieceStruct t;
500 	int w_pieces=0;
501 	int b_pieces=0;
502 	int w_pawns=0;
503 	int b_pawns=0;
504 
505 	b->winner = 0;
506 
507 	init_hash_values();
508 
509 	memset(b->pboard, 0, sizeof(b->pboard));
510 	memset(b->pieces, 0, sizeof(b->pieces));
511 	b->sliding_mask = 0;
512 	b->pawns7th = 0;
513 	b->hash1 = b->move_num & 1;
514 	b->hash2 = 0;
515 	b->piece_mask = 0;
516 	b->material_mask = 0;
517 	b->w_material = 0;
518 	b->b_material = 0;
519 	b->promotion = 0;
520 	b->wpassed_pawn_mask = 0;
521 	b->bpassed_pawn_mask = 0;
522 
523 	for (i=A1;i<=H8;i++) {
524 		Piece p = b->board[i];
525 		if (p == PAWN) {
526 			w_pawns++;
527 		} else if (p == -PAWN) {
528 			b_pawns++;
529 		} else if (p > PAWN) {
530 			pw->pos = i;
531 			pw->p = p;
532 			pw++;
533 			w_pieces++;
534 		} else if (p < -PAWN) {
535 			pb->pos = i;
536 			pb->p = p;
537 			pb++;
538 			b_pieces++;
539 		}
540 	}
541 
542 	pw = &WHITEPIECES(b)[16 - w_pawns];
543 	pb = &BLACKPIECES(b)[16 - b_pawns];
544 
545 	for (i=A1;i<=H8;i++) {
546 		Piece p = b->board[i];
547 		if (p == PAWN) {
548 			pw->pos = i;
549 			pw->p = p;
550 			pw++;
551 		} else if (p == -PAWN) {
552 			pb->pos = i;
553 			pb->p = p;
554 			pb++;
555 		}
556 	}
557 
558 	pw = WHITEPIECES(b);
559 	pb = BLACKPIECES(b);
560 
561 	qsort(pw, w_pieces, sizeof(*pw), piece_comp);
562 	qsort(pb, b_pieces, sizeof(*pb), piece_comp);
563 
564 	if (pw[0].p != KING || pb[0].p != -KING) {
565 		lprintf(0,"no king!\n");
566 		return 0;
567 	}
568 
569 	if (pw[IQUEEN].p != QUEEN) shiftup(pw, IQUEEN, &w_pieces);
570 	if (pw[IKROOK].p != ROOK) shiftup(pw, IKROOK, &w_pieces);
571 	if (pw[IQROOK].p != ROOK) shiftup(pw, IQROOK, &w_pieces);
572 	if (pw[IKBISHOP].p != BISHOP) shiftup(pw, IKBISHOP, &w_pieces);
573 	if (pw[IQBISHOP].p != BISHOP) shiftup(pw, IQBISHOP, &w_pieces);
574 	if (pw[IKKNIGHT].p != KNIGHT) shiftup(pw, IKKNIGHT, &w_pieces);
575 	if (pw[IQKNIGHT].p != KNIGHT) shiftup(pw, IQKNIGHT, &w_pieces);
576 
577 	if (pb[IQUEEN].p != -QUEEN) shiftup(pb, IQUEEN, &b_pieces);
578 	if (pb[IKROOK].p != -ROOK) shiftup(pb, IKROOK, &b_pieces);
579 	if (pb[IQROOK].p != -ROOK) shiftup(pb, IQROOK, &b_pieces);
580 	if (pb[IKBISHOP].p != -BISHOP) shiftup(pb, IKBISHOP, &b_pieces);
581 	if (pb[IQBISHOP].p != -BISHOP) shiftup(pb, IQBISHOP, &b_pieces);
582 	if (pb[IKKNIGHT].p != -KNIGHT) shiftup(pb, IKKNIGHT, &b_pieces);
583 	if (pb[IQKNIGHT].p != -KNIGHT) shiftup(pb, IQKNIGHT, &b_pieces);
584 
585 	if (pw[IKBISHOP].p && !white_square(pw[IKBISHOP].pos)) {
586 		t = pw[IKBISHOP];
587 		pw[IKBISHOP] = pw[IQBISHOP];
588 		pw[IQBISHOP] = t;
589 	}
590 
591 	if (pb[IKBISHOP].p && white_square(pb[IKBISHOP].pos)) {
592 		t = pb[IKBISHOP];
593 		pb[IKBISHOP] = pb[IQBISHOP];
594 		pb[IQBISHOP] = t;
595 	}
596 
597 	/* now the pboard */
598 	memset(b->board, 0, sizeof(b->board));
599 	memset(b->pboard, -1, sizeof(b->pboard));
600 
601 	pw = WHITEPIECES(b);
602 	for (i=0;i<32;i++, pw++) {
603 		if (pw->p)
604 			add_piece(b, pw->p, pw->pos, pw);
605 	}
606 
607 	if (b->board[E1] != KING) {
608 		b->flags &= ~(WHITE_CASTLE_SHORT | WHITE_CASTLE_LONG);
609 	}
610 
611 	if (b->board[E8] != -KING) {
612 		b->flags &= ~(BLACK_CASTLE_SHORT | BLACK_CASTLE_LONG);
613 	}
614 
615 	if (b->board[H1] != ROOK) {
616 		b->flags &= ~WHITE_CASTLE_SHORT;
617 	}
618 
619 	if (b->board[A1] != ROOK) {
620 		b->flags &= ~WHITE_CASTLE_LONG;
621 	}
622 
623 	if (b->board[H8] != -ROOK) {
624 		b->flags &= ~BLACK_CASTLE_SHORT;
625 	}
626 
627 	if (b->board[A8] != -ROOK) {
628 		b->flags &= ~BLACK_CASTLE_LONG;
629 	}
630 
631 	b->hash1 ^= (b->enpassent<<8);
632 	b->hash1 ^= (b->flags & (FLAG_CAN_CASTLE)) << 16;
633 
634 	regen_moves(b);
635 
636 	return 1;
637 }
638 
639 
640