1 /*
2 Sjeng - a chess variants playing program
3 Copyright (C) 2000 Gian-Carlo Pascutto
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 File: moves.c
20 Purpose: functions used to generate & make moves
21
22 */
23
24 #include "sjeng.h"
25 #include "extvars.h"
26 #include "protos.h"
27
28 unsigned long total_moves;
29 unsigned long total_movegens;
30
31 int numb_moves;
32 static move_s *genfor;
33
34 int fcaptures;
35 int gfrom;
36
37 int kingcap; /* break if we capture the king */
38
check_legal(move_s moves[],int m,int incheck)39 bool check_legal (move_s moves[], int m, int incheck) {
40
41 /* determines if a move made was legal. Checks to see if the player who
42 just moved castled through check, or is in check. If the move made
43 was illegal, returns FALSE, otherwise, returns TRUE. */
44
45 int castled = moves[m].castled;
46 int from = moves[m].from;
47 int target = moves[m].target;
48 int l;
49
50 if (Variant == Suicide) return TRUE;
51
52 /* check for castling moves: */
53 if (castled)
54 {
55 /* white kingside castling: */
56 if (castled == wck) {
57 if (is_attacked (30, 0)) return FALSE;
58 if (is_attacked (31, 0)) return FALSE;
59 if (is_attacked (32, 0)) return FALSE;
60 return TRUE;
61 }
62 /* white queenside castling: */
63 if (castled == wcq) {
64 if (is_attacked (30, 0)) return FALSE;
65 if (is_attacked (29, 0)) return FALSE;
66 if (is_attacked (28, 0)) return FALSE;
67 return TRUE;
68 }
69 /* black kingside castling: */
70 if (castled == bck) {
71 if (is_attacked (114, 1)) return FALSE;
72 if (is_attacked (115, 1)) return FALSE;
73 if (is_attacked (116, 1)) return FALSE;
74 return TRUE;
75 }
76 /* black queenside castling: */
77 if (castled == bcq) {
78 if (is_attacked (114, 1)) return FALSE;
79 if (is_attacked (113, 1)) return FALSE;
80 if (is_attacked (112, 1)) return FALSE;
81 return TRUE;
82 }
83 }
84
85 /* otherwise, just check on the kings: */
86 /* black king: */
87
88 /* the code in here checks whether a move could
89 * have put the king in check, if he was not in
90 * check before, if not, an early exit is taken */
91
92 else if (white_to_move&1)
93 {
94 if (!incheck)
95 {
96 if (moves[m].from == 0) return TRUE;
97
98 switch (moves[m].promoted ? bpawn : board[target])
99 {
100 case bpawn:
101 /* pawn moves, it can discover a rank or diagonal check
102 * a capture can also discover a file check */
103 if (moves[m].captured != npiece)
104 {
105 if (file(from) != file(bking_loc)
106 && rank(from) != rank(bking_loc)
107 && diagl(from) != diagl(bking_loc)
108 && diagr(from) != diagr(bking_loc))
109 return TRUE;
110 }
111 else
112 {
113 if (rank(from) != rank(bking_loc)
114 && diagl(from) != diagl(bking_loc)
115 && diagr(from) != diagr(bking_loc))
116 return TRUE;
117 }
118 break;
119 case bknight:
120 /* discovers all */
121 if (file(from) != file(bking_loc)
122 && rank(from) != rank(bking_loc)
123 && diagl(from) != diagl(bking_loc)
124 && diagr(from) != diagr(bking_loc))
125 return TRUE;
126 break;
127 case bbishop:
128 /* always discovers file and rank
129 * always discovers one diagonal */
130 if (file(from) != file(bking_loc)
131 && rank(from) != rank(bking_loc))
132 {
133 if (diagl(from) == diagl(target))
134 {
135 /* stays on diag, can only uncover check on
136 * other diag */
137 if (diagr(from) != diagr(bking_loc))
138 return TRUE;
139 }
140 else
141 {
142 if (diagl(from) != diagl(bking_loc))
143 return TRUE;
144 }
145 }
146 break;
147 case brook:
148 /* discovers diagonal always */
149 /* one file or rank discovered */
150 if (diagr(from) != diagr(bking_loc)
151 && diagl(from) != diagl(bking_loc))
152 {
153 /* rank move ? */
154 if(rank(from) == rank(target))
155 {
156 if (file(from) != file(bking_loc))
157 return TRUE;
158 }
159 else
160 {
161 /* file move */
162 if (rank(from) != rank(bking_loc))
163 return TRUE;
164 }
165 }
166 break;
167 case bqueen:
168 /* find out what move it was: ldiag/rdiag/file/rank*/
169 if (file(from) == file(target))
170 {
171 if (diagr(from) != diagr(bking_loc)
172 && diagl(from) != diagl(bking_loc)
173 && rank(from) != rank(bking_loc))
174 return TRUE;
175 }
176 else if (rank(from) == rank(target))
177 {
178 if (diagr(from) != diagr(bking_loc)
179 && file(from) != file(bking_loc)
180 && diagl(from) != diagl(bking_loc))
181 return TRUE;
182 }
183 else if (diagl(from) == diagl(target))
184 {
185 if (diagr(from) != diagr(bking_loc)
186 && file(from) != file(bking_loc)
187 && rank(from) != rank(bking_loc))
188 return TRUE;
189 }
190 else if (diagr(from) == diagr(target))
191 {
192 if (diagl(from) != diagl(bking_loc)
193 && file(from) != file(bking_loc)
194 && rank(from) != rank(bking_loc))
195 return TRUE;
196 }
197 break;
198 default:
199 break;
200 }
201
202 /* we got so far, we know there can only be some
203 * kind of possible discovering */
204 /* find out what */
205 /* we do not need to check for pawn, king or knightattacks,
206 * as they cannot be discovered*/
207
208 if (board[target] != bking)
209 {
210 if (file(from) == file(bking_loc))
211 {
212 if (bking_loc > from)
213 {
214 for (l = bking_loc-12; board[l] == npiece; l-=12);
215 if (board[l] == wrook || board[l] == wqueen) return FALSE;
216 }
217 else
218 {
219 for (l = bking_loc+12; board[l] == npiece; l+=12);
220 if (board[l] == wrook || board[l] == wqueen) return FALSE;
221 }
222 }
223 else if (rank(from) == rank(bking_loc))
224 {
225 if (bking_loc > from)
226 {
227 for (l = bking_loc-1; board[l] == npiece; l-=1);
228 if (board[l] == wrook || board[l] == wqueen) return FALSE;
229 }
230 else
231 {
232 for (l = bking_loc+1; board[l] == npiece; l+=1);
233 if (board[l] == wrook || board[l] == wqueen) return FALSE;
234 }
235 }
236 else if (diagl(from) == diagl(bking_loc))
237 {
238 if (bking_loc > from)
239 {
240 for (l = bking_loc-13; board[l] == npiece; l-=13);
241 if (board[l] == wbishop || board[l] == wqueen) return FALSE;
242 }
243 else
244 {
245 for (l = bking_loc+13; board[l] == npiece; l+=13);
246 if (board[l] == wbishop || board[l] == wqueen) return FALSE;
247 }
248 }
249 else if (diagr(from) == diagr(bking_loc))
250 {
251 if (bking_loc > from)
252 {
253 for (l = bking_loc-11; board[l] == npiece; l-=11);
254 if (board[l] == wbishop || board[l] == wqueen) return FALSE;
255 }
256 else
257 {
258 for (l = bking_loc+11; board[l] == npiece; l+=11);
259 if (board[l] == wbishop || board[l] == wqueen) return FALSE;
260 }
261 }
262 return TRUE;
263 }
264 }
265
266 if (is_attacked (bking_loc, 1)) return FALSE;
267 else return TRUE;
268 }
269
270 /* white king: */
271 else
272 {
273
274 if (!incheck)
275 {
276 if (moves[m].from == 0) return TRUE;
277
278 switch (moves[m].promoted ? wpawn : board[target])
279 {
280 case wpawn:
281 /* pawn moves, it can discover a rank or diagonal check
282 * a capture can also discover a file check */
283 if (moves[m].captured != npiece)
284 {
285 if (file(from) != file(wking_loc)
286 && rank(from) != rank(wking_loc)
287 && diagl(from) != diagl(wking_loc)
288 && diagr(from) != diagr(wking_loc))
289 return TRUE;
290 }
291 else
292 {
293 if (rank(from) != rank(wking_loc)
294 && diagl(from) != diagl(wking_loc)
295 && diagr(from) != diagr(wking_loc))
296 return TRUE;
297 }
298 break;
299 case wknight:
300 /* discovers all */
301 if (file(from) != file(wking_loc)
302 && rank(from) != rank(wking_loc)
303 && diagl(from) != diagl(wking_loc)
304 && diagr(from) != diagr(wking_loc))
305 return TRUE;
306 break;
307 case wbishop:
308 /* always discovers file and rank
309 * always discovers one diagonal */
310 if (file(from) != file(wking_loc)
311 && rank(from) != rank(wking_loc))
312 {
313 if (diagl(from) == diagl(target))
314 {
315 /* stays on diag, can only uncover check on
316 * other diag */
317 if (diagr(from) != diagr(wking_loc))
318 return TRUE;
319 }
320 else
321 {
322 if (diagl(from) != diagl(wking_loc))
323 return TRUE;
324 }
325 }
326 break;
327 case wrook:
328 /* discovers diagonal always */
329 /* one file or rank discovered */
330 if (diagr(from) != diagr(wking_loc)
331 && diagl(from) != diagl(wking_loc))
332 {
333 /* rank move ? */
334 if(rank(from) == rank(target))
335 {
336 if (file(from) != file(wking_loc))
337 return TRUE;
338 }
339 else
340 {
341 /* file move */
342 if (rank(from) != rank(wking_loc))
343 return TRUE;
344 }
345 }
346 break;
347 case wqueen:
348 /* find out what move it was: ldiag/rdiag/file/rank*/
349 if (file(from) == file(moves[m].target))
350 {
351 if (diagr(from) != diagr(wking_loc)
352 && diagl(from) != diagl(wking_loc)
353 && rank(from) != rank(wking_loc))
354 return TRUE;
355 }
356 else if (rank(from) == rank(target))
357 {
358 if (diagr(from) != diagr(wking_loc)
359 && file(from) != file(wking_loc)
360 && diagl(from) != diagl(wking_loc))
361 return TRUE;
362 }
363 else if (diagl(from) == diagl(target))
364 {
365 if (diagr(from) != diagr(wking_loc)
366 && file(from) != file(wking_loc)
367 && rank(from) != rank(wking_loc))
368 return TRUE;
369 }
370 else if (diagr(from) == diagr(target))
371 {
372 if (diagl(from) != diagl(wking_loc)
373 && file(from) != file(wking_loc)
374 && rank(from) != rank(wking_loc))
375 return TRUE;
376 }
377 break;
378 default:
379 break;
380 }
381
382 if (board[target] != wking)
383 {
384 if (file(from) == file(wking_loc))
385 {
386 if (wking_loc > from)
387 {
388 for (l = wking_loc-12; board[l] == npiece; l-=12);
389 if (board[l] == brook || board[l] == bqueen) return FALSE;
390 }
391 else
392 {
393 for (l = wking_loc+12; board[l] == npiece; l+=12);
394 if (board[l] == brook || board[l] == bqueen) return FALSE;
395 }
396 }
397 else if (rank(from) == rank(wking_loc))
398 {
399 if (wking_loc > from)
400 {
401 for (l = wking_loc-1; board[l] == npiece; l-=1);
402 if (board[l] == brook || board[l] == bqueen) return FALSE;
403 }
404 else
405 {
406 for (l = wking_loc+1; board[l] == npiece; l+=1);
407 if (board[l] == brook || board[l] == bqueen) return FALSE;
408 }
409 }
410 else if (diagl(from) == diagl(wking_loc))
411 {
412 if (wking_loc > from)
413 {
414 for (l = wking_loc-13; board[l] == npiece; l-=13);
415 if (board[l] == bbishop || board[l] == bqueen) return FALSE;
416 }
417 else
418 {
419 for (l = wking_loc+13; board[l] == npiece; l+=13);
420 if (board[l] == bbishop || board[l] == bqueen) return FALSE;
421 }
422 }
423 else if (diagr(from) == diagr(wking_loc))
424 {
425 if (wking_loc > from)
426 {
427 for (l = wking_loc-11; board[l] == npiece; l-=11);
428 if (board[l] == bbishop || board[l] == bqueen) return FALSE;
429 }
430 else
431 {
432 for (l = wking_loc+11; board[l] == npiece; l+=11);
433 if (board[l] == bbishop || board[l] == bqueen) return FALSE;
434 }
435 }
436 return TRUE;
437 }
438 }
439
440 if (is_attacked (wking_loc, 0)) return FALSE;
441 else return TRUE;
442 }
443
444 /* should never get here .. but just so it will compile :P */
445 return FALSE;
446
447 }
448
449
450 #define push_slide(t) if (board[(t)] != frame) push_slidE((t))
451 #define push_knight(t) if (board[(t)] != frame) push_knighT((t))
452
gen(move_s moves[])453 void gen (move_s moves[]) {
454
455 /* generate pseudo-legal moves, and place them in the moves array */
456
457 int from, a, j, i;
458
459 kingcap = FALSE;
460
461 numb_moves = 0;
462 genfor = &moves[0];
463
464 if (Variant == Suicide)
465 {
466 captures = FALSE;
467 fcaptures = FALSE;
468 };
469
470 restart:
471
472 /* generate white moves, if it is white to move: */
473 if (white_to_move) {
474 for (a = 1, j = 1;
475 (a <= piece_count)
476 && (((Variant != Suicide) && !kingcap)
477 || ((Variant == Suicide) && (fcaptures == captures)));
478 j++) {
479
480 i = pieces[j];
481
482 if (!i)
483 continue;
484 else
485 a++;
486
487 from = i;
488 gfrom = i;
489
490 switch (board[from]) {
491 case (wpawn):
492 /* pawn moves up one square: */
493 if (board[from+12] == npiece) {
494 /* only promotions when captures == TRUE */
495 if (rank (from) == 7 && ((Variant != Suicide) && (Variant != Losers))) {
496 push_pawn (from+12, FALSE);
497 }
498 else if (!captures) {
499 push_pawn (from+12, FALSE);
500
501 /* pawn moving up two squares on its first move: */
502 if (rank(from) == 2 && board[from+24] == npiece)
503 push_pawn_simple (from+24);
504 }
505 }
506 /* pawn capturing diagonally: */
507 if ((board[from+13]&1) == 0 && board[from+13] != frame)
508 push_pawn (from+13, FALSE);
509 /* pawn captruing diagonally: */
510 if ((board[from+11]&1) == 0 && board[from+11] != frame)
511 push_pawn (from+11, FALSE);
512 /* ep move: */
513 if (ep_square == from+13)
514 push_pawn (from+13, TRUE);
515 /* ep move: */
516 else if (ep_square == from+11)
517 push_pawn (from+11, TRUE);
518 break;
519 case (wknight):
520 /* use the knight offsets: */
521 push_knight (from-25);
522 push_knight (from-23);
523 push_knight (from-14);
524 push_knight (from-10);
525 push_knight (from+10);
526 push_knight (from+14);
527 push_knight (from+23);
528 push_knight (from+25);
529 break;
530 case (wbishop):
531 /* use the bishop offsets: */
532 push_slide (from-13);
533 push_slide (from-11);
534 push_slide (from+11);
535 push_slide (from+13);
536 break;
537 case (wrook):
538 /* use the rook offsets: */
539 push_slide (from-12);
540 push_slide (from-1);
541 push_slide (from+1);
542 push_slide (from+12);
543 break;
544 case (wqueen):
545 /* use the queen offsets: */
546 push_slide (from-13);
547 push_slide (from-12);
548 push_slide (from-11);
549 push_slide (from-1);
550 push_slide (from+1);
551 push_slide (from+11);
552 push_slide (from+12);
553 push_slide (from+13);
554 break;
555 case (wking):
556 /* use the king offsets for 'normal' moves: */
557 push_king (from-13);
558 push_king (from-12);
559 push_king (from-11);
560 push_king (from-1);
561 push_king (from+1);
562 push_king (from+11);
563 push_king (from+12);
564 push_king (from+13);
565 /* castling moves: */
566 if (from == 30 && !moved[30] && !captures && (Variant != Suicide || Giveaway == TRUE)) {
567 /* kingside: */
568 if (!moved[33] && board[33] == wrook)
569 if (board[31] == npiece && board[32] == npiece)
570 push_king_castle (from+2, wck);
571 /* queenside: */
572 if (!moved[26] && board[26] == wrook)
573 if (board[27] == npiece && board[28] == npiece
574 && board[29] == npiece)
575 push_king_castle (from-2, wcq);
576 }
577 break;
578 default:
579 break;
580 }
581 }
582 }
583
584 /* generate black moves, if it is black to move: */
585 else {
586 for (a = 1, j = 1;
587 (a <= piece_count) &&
588 (((Variant != Suicide) && !kingcap)
589 || ((Variant == Suicide) && (fcaptures == captures)))
590 ; j++) {
591 i = pieces[j];
592
593 if (!i)
594 continue;
595 else
596 a++;
597
598 from = i;
599 gfrom = i;
600
601 switch (board[from]) {
602 case (bpawn):
603 /* pawn moves up one square: */
604 if (board[from-12] == npiece) {
605 /* only promotions when captures == TRUE */
606 if (rank (from) == 2 && ((Variant != Suicide) && (Variant != Losers))) {
607 push_pawn (from-12, FALSE);
608 }
609 else if (!captures) {
610 push_pawn (from-12, FALSE);
611
612 /* pawn moving up two squares on its first move: */
613 if (rank(from) == 7 && board[from-24] == npiece)
614 push_pawn_simple (from-24);
615 }
616 };
617 /* pawn capturing diagonally: */
618 if ((board[from-13]&1) == 1 && board[from-13] != npiece)
619 push_pawn (from-13, FALSE);
620 /* pawn capturing diagonally: */
621 if ((board[from-11]&1) == 1 && board[from-11] != npiece)
622 push_pawn (from-11, FALSE);
623 /* ep move: */
624 if (ep_square == from-13)
625 push_pawn (from-13, TRUE);
626 /* ep move: */
627 else if (ep_square == from-11)
628 push_pawn (from-11, TRUE);
629 break;
630 case (bknight):
631 /* use the knight offsets: */
632 push_knight (from-25);
633 push_knight (from-23);
634 push_knight (from-14);
635 push_knight (from-10);
636 push_knight (from+10);
637 push_knight (from+14);
638 push_knight (from+23);
639 push_knight (from+25);
640 break;
641 case (bbishop):
642 /* use the bishop offsets: */
643 push_slide (from-13);
644 push_slide (from-11);
645 push_slide (from+11);
646 push_slide (from+13);
647 break;
648 case (brook):
649 /* use the rook offsets: */
650 push_slide (from-12);
651 push_slide (from-1);
652 push_slide (from+1);
653 push_slide (from+12);
654 break;
655 case (bqueen):
656 /* use the queen offsets: */
657 push_slide (from-13);
658 push_slide (from-12);
659 push_slide (from-11);
660 push_slide (from-1);
661 push_slide (from+1);
662 push_slide (from+11);
663 push_slide (from+12);
664 push_slide (from+13);
665 break;
666 case (bking):
667 /* use the king offsets for 'normal' moves: */
668 push_king (from-13);
669 push_king (from-12);
670 push_king (from-11);
671 push_king (from-1);
672 push_king (from+1);
673 push_king (from+11);
674 push_king (from+12);
675 push_king (from+13);
676 /* castling moves: */
677 if (from == 114 && !moved[114] && !captures && (Variant != Suicide || Giveaway == TRUE)) {
678 /* kingside: */
679 if (!moved[117] && board[117] == brook)
680 if (board[115] == npiece && board[116] == npiece)
681 push_king_castle (from+2, bck);
682 /* queenside: */
683 if (!moved[110] && board[110] == brook)
684 if (board[111] == npiece && board[112] == npiece
685 && board[113] == npiece)
686 push_king_castle (from-2, bcq);
687 }
688 break;
689 default:
690 break;
691 }
692 }
693 }
694 if (((Variant == Crazyhouse) || (Variant == Bughouse)) && !captures && !kingcap)
695 {
696 if (white_to_move &&
697 (holding[WHITE][wpawn] || holding[WHITE][wknight]
698 || holding[WHITE][wbishop] || holding[WHITE][wqueen]
699 || holding[WHITE][wrook]))
700 {
701 for (from = 26; from < 118; from++)
702 {
703 gfrom = from;
704
705 switch (board[from])
706 {
707 case (frame):
708 from += 3;
709 continue;
710 case (npiece):
711 if(holding[WHITE][wpawn])
712 {
713 if ((rank(from) != 8) && (rank(from) != 1))
714 {
715 try_drop(wpawn);
716 }
717 }
718 if(holding[WHITE][wknight])
719 {
720 try_drop(wknight);
721 }
722 if(holding[WHITE][wbishop])
723 {
724 try_drop(wbishop);
725 }
726 if(holding[WHITE][wrook])
727 {
728 try_drop(wrook);
729 }
730 if(holding[WHITE][wqueen])
731 {
732 try_drop(wqueen);
733 }
734 };
735 }
736 }
737 else if (!white_to_move &&
738 (holding[BLACK][bpawn] || holding[BLACK][bknight]
739 || holding[BLACK][bbishop] || holding[BLACK][bqueen]
740 || holding[BLACK][brook]))
741 {
742 for (from = 26; from < 118; from++)
743 {
744 gfrom = from;
745
746 switch (board[from])
747 {
748 case (frame):
749 from += 3;
750 continue;
751 case (npiece):
752 if(holding[BLACK][bpawn])
753 {
754 if ((rank(from) != 8) && (rank(from) != 1))
755 {
756 try_drop(bpawn);
757 }
758 }
759 if(holding[BLACK][bknight])
760 {
761 try_drop(bknight);
762 }
763 if(holding[BLACK][bbishop])
764 {
765 try_drop(bbishop);
766 }
767 if(holding[BLACK][brook])
768 {
769 try_drop(brook);
770 }
771 if(holding[BLACK][bqueen])
772 {
773 try_drop(bqueen);
774 }
775 };
776 };
777 }
778 }
779
780 if ((Variant == Suicide) && fcaptures == TRUE && captures == FALSE)
781 {
782 captures = TRUE;
783 numb_moves = 0;
784 goto restart;
785 }
786
787 if (Variant == Suicide) kingcap = FALSE;
788
789
790 }
791
792
in_check(void)793 bool in_check (void) {
794
795 /* return true if the side to move is in check: */
796
797 if (Variant == Suicide) return FALSE;
798
799 if (white_to_move == 1) {
800 if (is_attacked (wking_loc, 0)) {
801 return TRUE;
802 }
803 }
804 else {
805 if (is_attacked (bking_loc, 1)) {
806 return TRUE;
807 }
808 }
809
810 return FALSE;
811
812 }
813
f_in_check(move_s moves[],int m)814 bool f_in_check(move_s moves[], int m)
815 {
816 int target = moves[m].target;
817 int from = moves[m].from;
818 int l;
819 static const int knight_o[8] = {10, -10, 14, -14, 23, -23, 25, -25};
820
821 if (Variant == Suicide) return FALSE;
822
823 if (white_to_move == 1)
824 {
825 /* is white king attacked */
826 /* we are certain the king is not in check already,
827 * as we would capture him in our ply */
828 /* thus, we need to check if our move could possibly
829 * put the king in check */
830 /* this can either be a direct check, or a discover */
831
832 switch (board[target])
833 {
834 case bpawn:
835 if (board[target-11] == wking || board[target-13] == wking) return TRUE;
836 break;
837 case bbishop:
838 if (diagl(target) == diagl(wking_loc))
839 {
840 /* possible left diag check */
841 if (wking_loc < target)
842 {
843 for (l = wking_loc+13; board[l] == npiece; l +=13);
844 if (l == target) return TRUE;
845 }
846 else
847 {
848 for (l = wking_loc-13; board[l] == npiece; l -=13);
849 if (l == target) return TRUE;
850 }
851 }
852 else if (diagr(target) == diagr(wking_loc))
853 {
854 if (wking_loc < target)
855 {
856 for (l = wking_loc+11; board[l] == npiece; l +=11);
857 if (l == target) return TRUE;
858 }
859 else
860 {
861 for (l = wking_loc-11; board[l] == npiece; l -=11);
862 if (l == target) return TRUE;
863 }
864 }
865 break;
866 case brook:
867 if (file(target) == file(wking_loc))
868 {
869 if (wking_loc < target)
870 {
871 for (l = wking_loc+12; board[l] == npiece; l +=12);
872 if (l == target) return TRUE;
873 }
874 else
875 {
876 for (l = wking_loc-12; board[l] == npiece; l -=12);
877 if (l == target) return TRUE;
878 }
879 }
880 else if (rank(target) == rank(wking_loc))
881 {
882 if (wking_loc < target)
883 {
884 for (l = wking_loc+1; board[l] == npiece; l++);
885 if (l == target) return TRUE;
886 }
887 else
888 {
889 for (l = wking_loc-1; board[l] == npiece; l--);
890 if (l == target) return TRUE;
891 }
892 }
893 break;
894 case bknight:
895 for (l = 0; l < 8; l++)
896 if ((wking_loc + knight_o[l]) == target) return TRUE;
897 break;
898 case bqueen:
899 if (file(target) == file(wking_loc))
900 {
901 if (wking_loc < target)
902 {
903 for (l = wking_loc+12; board[l] == npiece; l +=12);
904 if (l == target) return TRUE;
905 }
906 else
907 {
908 for (l = wking_loc-12; board[l] == npiece; l -=12);
909 if (l == target) return TRUE;
910 }
911 }
912 else if (rank(target) == rank(wking_loc))
913 {
914 if (wking_loc < target)
915 {
916 for (l = wking_loc+1; board[l] == npiece; l +=1);
917 if (l == target) return TRUE;
918 }
919 else
920 {
921 for (l = wking_loc-1; board[l] == npiece; l -=1);
922 if (l == target) return TRUE;
923 }
924 }
925 else if (diagl(target) == diagl(wking_loc))
926 {
927 if (wking_loc < target)
928 {
929 for (l = wking_loc+13; board[l] == npiece; l +=13);
930 if (l == target) return TRUE;
931 }
932 else
933 {
934 for (l = wking_loc-13; board[l] == npiece; l -=13);
935 if (l == target) return TRUE;
936 }
937 }
938 else if (diagr(target) == diagr(wking_loc))
939 {
940 if (wking_loc < target)
941 {
942 for (l = wking_loc+11; board[l] == npiece; l +=11);
943 if (l == target) return TRUE;
944 }
945 else
946 {
947 for (l = wking_loc-11; board[l] == npiece; l -=11);
948 if (l == target) return TRUE;
949 }
950 }
951 break;
952 case bking:
953 /* can only discover checks */
954 /* castling is tricky */
955 if (moves[m].castled)
956 {
957 if (is_attacked (wking_loc, 0))
958 return TRUE;
959 else
960 return FALSE;
961 }
962 break;
963 }
964
965 /* drop move can never discover check */
966 if (from == 0) return FALSE;
967
968 /* this checks for discovered checks */
969 if (rank(from) == rank(wking_loc))
970 {
971 if (wking_loc > from)
972 {
973 for (l = wking_loc-1; board[l] == npiece; l--);
974 if (board[l] == brook || board[l] == bqueen) return TRUE;
975 }
976 else
977 {
978 for (l = wking_loc+1; board[l] == npiece; l++);
979 if (board[l] == brook || board[l] == bqueen) return TRUE;
980 }
981 }
982 else if (file(from) == file(wking_loc))
983 {
984 if (wking_loc > from)
985 {
986 for (l = wking_loc-12; board[l] == npiece; l-=12);
987 if (board[l] == brook || board[l] == bqueen) return TRUE;
988 }
989 else
990 {
991 for (l = wking_loc+12; board[l] == npiece; l+=12);
992 if (board[l] == brook || board[l] == bqueen) return TRUE;
993 }
994 }
995 else if (diagl(from) == diagl(wking_loc))
996 {
997 if (wking_loc > from)
998 {
999 for (l = wking_loc-13; board[l] == npiece; l-=13);
1000 if (board[l] == bbishop || board[l] == bqueen) return TRUE;
1001 }
1002 else
1003 {
1004 for (l = wking_loc+13; board[l] == npiece; l+=13);
1005 if (board[l] == bbishop || board[l] == bqueen) return TRUE;
1006 }
1007 }
1008 else if (diagr(from) == diagr(wking_loc))
1009 {
1010 if (wking_loc > from)
1011 {
1012 for (l = wking_loc-11; board[l] == npiece; l-=11);
1013 if (board[l] == bbishop || board[l] == bqueen) return TRUE;
1014 }
1015 else
1016 {
1017 for (l = wking_loc+11; board[l] == npiece; l+=11);
1018 if (board[l] == bbishop || board[l] == bqueen) return TRUE;
1019 }
1020 }
1021
1022 return FALSE;
1023
1024 //if (is_attacked (wking_loc, 0))
1025 //return TRUE;
1026 }
1027 else
1028 {
1029 /* is black king attacked */
1030 switch (board[target])
1031 {
1032 case wpawn:
1033 if (board[target+11] == bking || board[target+13] == bking) return TRUE;
1034 break;
1035 case wbishop:
1036 if (diagl(target) == diagl(bking_loc))
1037 {
1038 /* possible left diag check */
1039 if (bking_loc < target)
1040 {
1041 for (l = bking_loc+13; board[l] == npiece; l +=13);
1042 if (l == target) return TRUE;
1043 }
1044 else
1045 {
1046 for (l = bking_loc-13; board[l] == npiece; l -=13);
1047 if (l == target) return TRUE;
1048 }
1049 }
1050 else if (diagr(target) == diagr(bking_loc))
1051 {
1052 if (bking_loc < target)
1053 {
1054 for (l = bking_loc+11; board[l] == npiece; l +=11);
1055 if (l == target) return TRUE;
1056 }
1057 else
1058 {
1059 for (l = bking_loc-11; board[l] == npiece; l -=11);
1060 if (l == target) return TRUE;
1061 }
1062 }
1063 break;
1064 case wrook:
1065 if (file(target) == file(bking_loc))
1066 {
1067 if (bking_loc < target)
1068 {
1069 for (l = bking_loc+12; board[l] == npiece; l +=12);
1070 if (l == target) return TRUE;
1071 }
1072 else
1073 {
1074 for (l = bking_loc-12; board[l] == npiece; l -=12);
1075 if (l == target) return TRUE;
1076 }
1077 }
1078 else if (rank(target) == rank(bking_loc))
1079 {
1080 if (bking_loc < target)
1081 {
1082 for (l = bking_loc+1; board[l] == npiece; l++);
1083 if (l == target) return TRUE;
1084 }
1085 else
1086 {
1087 for (l = bking_loc-1; board[l] == npiece; l--);
1088 if (l == target) return TRUE;
1089 }
1090 }
1091 break;
1092 case wknight:
1093 for (l = 0; l < 8; l++)
1094 if ((bking_loc + knight_o[l]) == target) return TRUE;
1095 break;
1096 case wqueen:
1097 if (file(target) == file(bking_loc))
1098 {
1099 if (bking_loc < target)
1100 {
1101 for (l = bking_loc+12; board[l] == npiece; l +=12);
1102 if (l == target) return TRUE;
1103 }
1104 else
1105 {
1106 for (l = bking_loc-12; board[l] == npiece; l -=12);
1107 if (l == target) return TRUE;
1108 }
1109 }
1110 else if (rank(target) == rank(bking_loc))
1111 {
1112 if (bking_loc < target)
1113 {
1114 for (l = bking_loc+1; board[l] == npiece; l +=1);
1115 if (l == target) return TRUE;
1116 }
1117 else
1118 {
1119 for (l = bking_loc-1; board[l] == npiece; l -=1);
1120 if (l == target) return TRUE;
1121 }
1122 }
1123 else if (diagl(target) == diagl(bking_loc))
1124 {
1125 if (bking_loc < target)
1126 {
1127 for (l = bking_loc+13; board[l] == npiece; l +=13);
1128 if (l == target) return TRUE;
1129 }
1130 else
1131 {
1132 for (l = bking_loc-13; board[l] == npiece; l -=13);
1133 if (l == target) return TRUE;
1134 }
1135 }
1136 else if (diagr(target) == diagr(bking_loc))
1137 {
1138 if (bking_loc < target)
1139 {
1140 for (l = bking_loc+11; board[l] == npiece; l +=11);
1141 if (l == target) return TRUE;
1142 }
1143 else
1144 {
1145 for (l = bking_loc-11; board[l] == npiece; l -=11);
1146 if (l == target) return TRUE;
1147 }
1148 }
1149 break;
1150 case wking:
1151 /* can only discover checks */
1152 if (moves[m].castled)
1153 {
1154 if (is_attacked (bking_loc, 1))
1155 return TRUE;
1156 else
1157 return FALSE;
1158 }
1159 break;
1160 }
1161
1162 if (from == 0) return FALSE;
1163
1164 /* this checks for discovered checks */
1165 if (rank(from) == rank(bking_loc))
1166 {
1167 if (bking_loc > from)
1168 {
1169 for (l = bking_loc-1; board[l] == npiece; l--);
1170 if (board[l] == wrook || board[l] == wqueen) return TRUE;
1171 }
1172 else
1173 {
1174 for (l = bking_loc+1; board[l] == npiece; l++);
1175 if (board[l] == wrook || board[l] == wqueen) return TRUE;
1176 }
1177 }
1178 else if (file(from) == file(bking_loc))
1179 {
1180 if (bking_loc > from)
1181 {
1182 for (l = bking_loc-12; board[l] == npiece; l-=12);
1183 if (board[l] == wrook || board[l] == wqueen) return TRUE;
1184 }
1185 else
1186 {
1187 for (l = bking_loc+12; board[l] == npiece; l+=12);
1188 if (board[l] == wrook || board[l] == wqueen) return TRUE;
1189 }
1190 }
1191 else if (diagl(from) == diagl(bking_loc))
1192 {
1193 if (bking_loc > from)
1194 {
1195 for (l = bking_loc-13; board[l] == npiece; l-=13);
1196 if (board[l] == wbishop || board[l] == wqueen) return TRUE;
1197 }
1198 else
1199 {
1200 for (l = bking_loc+13; board[l] == npiece; l+=13);
1201 if (board[l] == wbishop || board[l] == wqueen) return TRUE;
1202 }
1203 }
1204 else if (diagr(from) == diagr(bking_loc))
1205 {
1206 if (bking_loc > from)
1207 {
1208 for (l = bking_loc-11; board[l] == npiece; l-=11);
1209 if (board[l] == wbishop || board[l] == wqueen) return TRUE;
1210 }
1211 else
1212 {
1213 for (l = bking_loc+11; board[l] == npiece; l+=11);
1214 if (board[l] == wbishop || board[l] == wqueen) return TRUE;
1215 }
1216 }
1217
1218 return FALSE;
1219
1220 // if (is_attacked (bking_loc, 1))
1221 // display_board(stdout, 1);//return TRUE;
1222 }
1223 }
1224
extended_in_check(void)1225 int extended_in_check(void)
1226 {
1227 register int sq;
1228 static const int knight_o[8] = {10, -10, 14, -14, 23, -23, 25, -25};
1229
1230 if (Variant == Suicide) return 0;
1231
1232 if (white_to_move == 1)
1233 {
1234 sq = board[wking_loc-12];
1235 if (sq == brook || sq == bqueen) return 2;
1236 sq = board[wking_loc-1];
1237 if (sq == brook || sq == bqueen) return 2;
1238 sq = board[wking_loc+1];
1239 if (sq == brook || sq == bqueen) return 2;
1240 sq = board[wking_loc+12];
1241 if (sq == brook || sq == bqueen) return 2;
1242 sq = board[wking_loc+13];
1243 if (sq == bbishop || sq == bqueen || sq == bpawn) return 2;
1244 sq = board[wking_loc+11];
1245 if (sq == bbishop || sq == bqueen || sq == bpawn) return 2;
1246 sq = board[wking_loc-11];
1247 if (sq == bbishop || sq == bqueen) return 2;
1248 sq = board[wking_loc-13];
1249 if (sq == bbishop || sq == bqueen) return 2;
1250 for (sq = 0; sq < 8; sq++)
1251 {
1252 if (board[wking_loc + knight_o[sq]] == bknight) return 2;
1253 }
1254 if (is_attacked (wking_loc, 0))
1255 {
1256 if (Variant == Normal || Variant == Losers) return 2;
1257 else return 1;
1258 }
1259 }
1260 else
1261 {
1262 sq = board[bking_loc-12];
1263 if (sq == wrook || sq == wqueen) return 2;
1264 sq = board[bking_loc-1];
1265 if (sq == wrook || sq == wqueen) return 2;
1266 sq = board[bking_loc+1];
1267 if (sq == wrook || sq == wqueen) return 2;
1268 sq = board[bking_loc+12];
1269 if (sq == wrook || sq == wqueen) return 2;
1270 sq = board[bking_loc-13];
1271 if (sq == wbishop || sq == wqueen || sq == wpawn) return 2;
1272 sq = board[bking_loc-11];
1273 if (sq == wbishop || sq == wqueen || sq == wpawn) return 2;
1274 sq = board[bking_loc+11];
1275 if (sq == wbishop || sq == wqueen) return 2;
1276 sq = board[bking_loc+13];
1277 if (sq == wbishop || sq == wqueen) return 2;
1278 for (sq = 0; sq < 8; sq++)
1279 {
1280 if (board[bking_loc + knight_o[sq]] == wknight) return 2;
1281 }
1282 if (is_attacked (bking_loc, 1))
1283 {
1284 if (Variant == Normal || Variant == Losers) return 2;
1285 else return 1;
1286 }
1287 }
1288
1289 return 0;
1290 };
1291
make(move_s moves[],int i)1292 void make (move_s moves[], int i) {
1293
1294 /* make a move */
1295
1296 /* rather than writing out from[i].from, from[i].target, etc. all over
1297 the place, just make a copy of them here: */
1298 int ep, from, target, captured, promoted, castled, find_slot;
1299 ep = moves[i].ep;
1300 from = moves[i].from;
1301 target = moves[i].target;
1302 captured = moves[i].captured;
1303 promoted = moves[i].promoted;
1304 castled = moves[i].castled;
1305
1306 //if ((moves[i].target == 0) || ((moves[i].from != 0) && ((board[moves[i].from] == npiece) || board[moves[i].from] == frame)))
1307 // DIE;
1308
1309 /* clear the en passant rights: */
1310 path_x[ply].epsq = ep_square;
1311
1312 ep_square = 0;
1313
1314 /* update the 50 move info: */
1315 path_x[ply].fifty = fifty;
1316
1317 /* ignore piece drops...50move draw wont happen anyway */
1318 if (board[from] == wpawn || board[from] == bpawn || board[target] != npiece)
1319 {
1320 fifty = 0;
1321 }
1322 else
1323 {
1324 fifty++;
1325 }
1326
1327 if (from == 0)
1328 { /* drop move */
1329 /* Drop moves are handled fully seperate because we exepect to encouter
1330 lots of them and we try to skip as many checks as possible.
1331 Note that the critical path for drop moves is very short.
1332 Also, we have to handle pieces[] and squares[] specially */
1333
1334 /* new piece on board */
1335 piece_count++;
1336
1337 /* find first empty slot in pieces[] */
1338 for(find_slot = 1; (pieces[find_slot] != 0); find_slot++)
1339 assert(find_slot < 63);
1340
1341 /* add to piece array, set piece-square pointer */
1342 pieces[find_slot] = target;
1343
1344 path_x[ply].was_promoted = is_promoted[find_slot];
1345 is_promoted[find_slot] = 0;
1346
1347 /* set square->piece pointer */
1348 squares[target] = find_slot;
1349 // moved[target] = 1;
1350
1351 //if (promoted <= frame || promoted >= npiece)
1352 // DIE;
1353
1354 assert(promoted > frame && promoted < npiece);
1355
1356 DropremoveHolding(promoted, ToMove);
1357
1358 /* piece went off holding but onto board */
1359 AddMaterial(promoted);
1360
1361 /* put our piece on the board */
1362 board[target] = promoted;
1363
1364 Hash(promoted,target);
1365
1366 white_to_move ^= 1;
1367 ply++;
1368
1369 return;
1370 }
1371 else
1372 {
1373
1374 path_x[ply].was_promoted = is_promoted[squares[target]];
1375
1376 /* update the "general" pieces[] / squares[] info (special moves need
1377 special handling later): */
1378 path_x[ply].cap_num = squares[target];
1379 pieces[squares[target]] = 0;
1380 pieces[squares[from]] = target;
1381 squares[target] = squares[from];
1382 squares[from] = 0;
1383
1384 /* update the piece count & add Holdings */
1385 if (!ep)
1386 {
1387 switch (board[target]) {
1388 case (npiece): break;
1389 default:
1390
1391 if (Variant == Bughouse || Variant == Crazyhouse)
1392 {
1393 if (path_x[ply].was_promoted)
1394 {
1395 addHolding(SwitchPromoted(board[target]), ToMove);
1396 }
1397 else
1398 {
1399 addHolding(SwitchColor(board[target]), ToMove);
1400 }
1401 }
1402
1403 RemoveMaterial(board[target]);
1404
1405 /* remove captured piece */
1406 Hash(board[target], target);
1407
1408 piece_count--;
1409 break;
1410 }
1411 }
1412
1413 /* white pawn moves: */
1414 if (board[from] == wpawn) {
1415 /* look for a promotion move: */
1416 if (promoted) {
1417 board[target] = promoted;
1418 board[from] = npiece;
1419 moved[target]++;
1420 moved[from]++;
1421 white_to_move ^= 1;
1422
1423 is_promoted[squares[target]] = 1;
1424
1425 /* remove pawn */
1426 Hash(wpawn, from);
1427 /* add new stuff */
1428 Hash(promoted, target);
1429
1430 RemoveMaterial(wpawn);
1431 AddMaterial(promoted);
1432
1433 ply++;
1434
1435 return;
1436 }
1437
1438 /* look for an en passant move: */
1439 if (ep) {
1440
1441 /* remove pawn */
1442 Hash(wpawn, from);
1443 /* remove ep pawn */
1444 Hash(bpawn, target-12);
1445 /* add target pawn */
1446 Hash(wpawn, target);
1447
1448 RemoveMaterial(bpawn);
1449
1450 board[target] = wpawn;
1451 board[from] = npiece;
1452
1453 addHolding(wpawn, WHITE);
1454 piece_count--;
1455
1456 board[target-12] = npiece;
1457 moved[target]++;
1458 moved[from]++;
1459 moved[target-12]++;
1460 white_to_move ^= 1;
1461 path_x[ply].cap_num = squares[target-12];
1462
1463 pieces[squares[target-12]] = 0;
1464 squares[target-12] = 0;
1465
1466 ply++;
1467
1468 return;
1469 }
1470
1471 /* otherwise, we have a "regular" pawn move: */
1472 /* first check to see if we've moved a pawn up 2 squares: */
1473 if (target == from+24)
1474 ep_square = from+12;
1475
1476 Hash(wpawn, from);
1477 Hash(wpawn, target);
1478
1479 board[target] = wpawn;
1480 board[from] = npiece;
1481 moved[target]++;
1482 moved[from]++;
1483 white_to_move ^= 1;
1484
1485 ply++;
1486
1487 return;
1488
1489 }
1490
1491 /* black pawn moves: */
1492 if (board[from] == bpawn) {
1493 /* look for a promotion move: */
1494 if (promoted) {
1495 board[target] = promoted;
1496 board[from] = npiece;
1497 moved[target]++;
1498 moved[from]++;
1499 white_to_move ^= 1;
1500
1501 is_promoted[squares[target]] = 1;
1502
1503 /* remove pawn */
1504 Hash(bpawn, from);
1505 /* add new stuff */
1506 Hash(promoted, target);
1507
1508 RemoveMaterial(bpawn);
1509 AddMaterial(promoted);
1510
1511 ply++;
1512
1513 return;
1514 }
1515
1516 /* look for an en passant move: */
1517 if (ep) {
1518
1519 /* remove pawn */
1520 Hash(bpawn, from);
1521 /* remove ep pawn */
1522 Hash(wpawn, target+12);
1523 /* add target pawn */
1524 Hash(bpawn, target);
1525
1526 RemoveMaterial(wpawn);
1527
1528 board[target] = bpawn;
1529 board[from] = npiece;
1530
1531 addHolding(bpawn, BLACK);
1532 piece_count--;
1533
1534 board[target+12] = npiece;
1535 moved[target]++;
1536 moved[from]++;
1537 moved[target+12]++;
1538 white_to_move ^= 1;
1539 path_x[ply].cap_num = squares[target+12];
1540 pieces[squares[target+12]] = 0;
1541 squares[target+12] = 0;
1542
1543 ply++;
1544
1545 return;
1546 }
1547
1548 /* otherwise, we have a "regular" pawn move: */
1549 /* first check to see if we've moved a pawn down 2 squares: */
1550 if (target == from-24)
1551 ep_square = from-12;
1552
1553 board[target] = bpawn;
1554 board[from] = npiece;
1555 moved[target]++;
1556 moved[from]++;
1557 white_to_move ^= 1;
1558
1559 Hash(bpawn, from);
1560 Hash(bpawn, target);
1561
1562 ply++;
1563
1564 return;
1565 }
1566
1567 /* piece moves, other than the king: */
1568 if (board[from] != wking && board[from] != bking) {
1569
1570 Hash(board[from], from);
1571 Hash(board[from], target);
1572
1573 board[target] = board[from];
1574 board[from] = npiece;
1575 moved[target]++;
1576 moved[from]++;
1577 white_to_move ^= 1;
1578
1579 ply++;
1580
1581 return;
1582 }
1583
1584 /* otherwise, we have a king move of some kind: */
1585 /* White king moves first: */
1586 if (board[from] == wking) {
1587 /* record the new white king location: */
1588 wking_loc = target;
1589
1590 /* perform the white king's move: */
1591 board[target] = wking;
1592 board[from] = npiece;
1593 moved[target]++;
1594 moved[from]++;
1595 white_to_move ^= 1;
1596
1597 Hash(wking, from);
1598 Hash(wking, target);
1599
1600 /* check for castling: */
1601 /* check for white kingside castling: */
1602 if (castled == wck) {
1603 board[33] = npiece;
1604 board[31] = wrook;
1605 moved[33]++;
1606 moved[31]++;
1607 white_castled = wck;
1608 pieces[squares[33]] = 31;
1609 squares[31] = squares[33];
1610 squares[33] = 0;
1611
1612 Hash(wrook, 33);
1613 Hash(wrook, 31);
1614
1615 ply++;
1616
1617 return;
1618 }
1619
1620 /* check for white queenside castling: */
1621 else if (castled == wcq) {
1622 board[26] = npiece;
1623 board[29] = wrook;
1624 moved[26]++;
1625 moved[29]++;
1626 white_castled = wcq;
1627 pieces[squares[26]] = 29;
1628 squares[29] = squares[26];
1629 squares[26] = 0;
1630
1631 Hash(wrook, 26);
1632 Hash(wrook, 29);
1633
1634 ply++;
1635
1636 return;
1637 }
1638
1639 ply++;
1640
1641 return;
1642 }
1643
1644 /* now we have only black king moves left: */
1645 else {
1646 /* record the new black king location: */
1647 bking_loc = target;
1648
1649 /* perform the black king's move: */
1650 board[target] = bking;
1651 board[from] = npiece;
1652 moved[target]++;
1653 moved[from]++;
1654 white_to_move ^= 1;
1655
1656 Hash(bking, from);
1657 Hash(bking, target);
1658
1659 /* check for castling: */
1660 /* check for black kingside castling: */
1661 if (castled == bck) {
1662 board[117] = npiece;
1663 board[115] = brook;
1664 moved[117]++;
1665 moved[115]++;
1666 black_castled = bck;
1667 pieces[squares[117]] = 115;
1668 squares[115] = squares[117];
1669 squares[117] = 0;
1670
1671 Hash(brook, 117);
1672 Hash(brook, 115);
1673
1674 ply++;
1675
1676 return;
1677 }
1678
1679 /* check for black queenside castling: */
1680 else if (castled == bcq) {
1681 board[110] = npiece;
1682 board[113] = brook;
1683 moved[110]++;
1684 moved[113]++;
1685 black_castled = bcq;
1686 pieces[squares[110]] = 113;
1687 squares[113] = squares[110];
1688 squares[110] = 0;
1689
1690 Hash(brook, 110);
1691 Hash(brook, 113);
1692
1693 ply++;
1694
1695 return;
1696 }
1697 }
1698 ply++;
1699
1700 return;
1701 }
1702 }
1703
add_move(int Ptarget,int Ppromoted)1704 void add_move(int Ptarget,
1705 int Ppromoted)
1706 {
1707 genfor[numb_moves].from = gfrom;
1708 genfor[numb_moves].target = Ptarget;
1709 genfor[numb_moves].captured = npiece;
1710 genfor[numb_moves].castled = no_castle;
1711 genfor[numb_moves].promoted = Ppromoted;
1712 genfor[numb_moves].ep = FALSE;
1713 numb_moves++;
1714
1715 return;
1716 }
1717
add_capture(int Ptarget,int Pcaptured,int Ppromoted,int Pep)1718 void add_capture(int Ptarget,
1719 int Pcaptured,
1720 int Ppromoted,
1721 int Pep)
1722 {
1723 if ((Variant != Suicide) && (Pcaptured == wking || Pcaptured == bking))
1724 {
1725 kingcap = TRUE;
1726 return;
1727 }
1728 else
1729 if (Pcaptured != npiece) fcaptures = TRUE;
1730
1731 genfor[numb_moves].from = gfrom;
1732 genfor[numb_moves].target = Ptarget;
1733 genfor[numb_moves].captured = Pcaptured;
1734 genfor[numb_moves].castled = no_castle;
1735 genfor[numb_moves].promoted = Ppromoted;
1736 genfor[numb_moves].ep = Pep;
1737 numb_moves++;
1738
1739 return;
1740 }
1741
try_drop(int ptype)1742 void try_drop (int ptype)
1743 {
1744 genfor[numb_moves].from = 0;
1745 genfor[numb_moves].target = gfrom;
1746 genfor[numb_moves].captured = npiece;
1747 genfor[numb_moves].castled = no_castle;
1748 genfor[numb_moves].promoted = ptype;
1749 genfor[numb_moves].ep = FALSE;
1750 numb_moves++;
1751
1752 return;
1753 }
1754
push_king_castle(int Ptarget,int Pcastle_type)1755 void push_king_castle (int Ptarget, int Pcastle_type)
1756 {
1757 genfor[numb_moves].from = gfrom;
1758 genfor[numb_moves].target = Ptarget;
1759 genfor[numb_moves].captured = npiece;
1760 genfor[numb_moves].castled = Pcastle_type;
1761 genfor[numb_moves].promoted = 0;
1762 genfor[numb_moves].ep = FALSE;
1763 numb_moves++;
1764
1765 return;
1766 }
1767
push_king(int target)1768 void push_king (int target) {
1769
1770 /* add king moves to the moves array */
1771
1772 /* first see if the move will take the king off the board: */
1773 if (board[target] == frame)
1774 return;
1775
1776 /* check to see if we have a non capture when in qsearch: */
1777 if (board[target] == npiece && captures)
1778 return;
1779
1780 /* non-capture, 'normal' king moves: */
1781 if (board[target] == npiece) {
1782 add_move(target, 0);
1783 return;
1784 }
1785
1786 /* 'normal' capture moves by the king: */
1787 else if ((board[target]&1) != (board[gfrom]&1)) {
1788 add_capture(target, board[target], 0, FALSE);
1789 return;
1790 }
1791
1792 /* no more possible moves for the king, so return: */
1793 return;
1794 }
1795
1796
push_knighT(int target)1797 void push_knighT (int target) {
1798
1799 /* add knight moves to the moves array */
1800
1801 /* check to see if we have a non capture when in qsearch: */
1802 if (board[target] == npiece && captures)
1803 return;
1804
1805 /* check for a non-capture knight move: */
1806 if (board[target] == npiece) {
1807 add_move(target, 0);
1808 return;
1809 }
1810
1811 /* check for a capture knight move: */
1812 else if ((board[target]&1) != (board[gfrom]&1)) {
1813 add_capture(target, board[target], 0, FALSE);
1814 return;
1815 }
1816
1817 /* no more possible moves left for the knight, so return: */
1818 return;
1819 }
1820
1821
push_pawn(int target,bool is_ep)1822 void push_pawn (int target, bool is_ep) {
1823
1824 /* add pawn moves to the moves array */
1825
1826 int captured_piece;
1827
1828 /* check to see if it's an ep move: */
1829 if (is_ep) {
1830 if (board[gfrom] == wpawn) {
1831 add_capture(target, bpawn, 0, TRUE);
1832 return;
1833 }
1834 else {
1835 add_capture(target, wpawn, 0, TRUE);
1836 return;
1837 }
1838 }
1839
1840 /* record which piece we are taking, so we don't have to compute it over
1841 and over again: */
1842 captured_piece = board[target];
1843
1844 /* look for a white promotion move: */
1845 if (board[gfrom] == wpawn && rank(gfrom) == 7) {
1846 add_capture(target, captured_piece, wqueen, FALSE);
1847 add_capture(target, captured_piece, wrook, FALSE);
1848 add_capture(target, captured_piece, wbishop, FALSE);
1849 add_capture(target, captured_piece, wknight, FALSE);
1850 if (Variant == Suicide)
1851 add_capture(target, captured_piece, wking, FALSE);
1852 /* we've finished generating all the promotions: */
1853 return;
1854 }
1855
1856 /* look for a black promotion move: */
1857 else if (board[gfrom] == bpawn && rank(gfrom) == 2) {
1858 add_capture(target, captured_piece, bqueen, FALSE);
1859 add_capture(target, captured_piece, brook, FALSE);
1860 add_capture(target, captured_piece, bbishop, FALSE);
1861 add_capture(target, captured_piece, bknight, FALSE);
1862 if (Variant == Suicide)
1863 add_capture(target, captured_piece, bking, FALSE);
1864 /* we've finished generating all the promotions: */
1865 return;
1866 }
1867
1868 /* otherwise, we have a normal pawn move: */
1869 else {
1870 add_capture(target, captured_piece, 0, FALSE);
1871 return;
1872 }
1873
1874 /* the function should never get here, but just for completeness: */
1875 return;
1876 }
1877
push_pawn_simple(int target)1878 void push_pawn_simple (int target) {
1879
1880 /* add pawn moves to the moves array */
1881
1882 add_move(target, 0);
1883 return;
1884 }
1885
push_slidE(int target)1886 void push_slidE (int target) {
1887
1888 /* add moves for sliding pieces to the moves array */
1889
1890 int offset;
1891 int mycolor;
1892
1893 /* check to see if we have gone off the board first: */
1894 // if (board[target] == frame)
1895 // return;
1896
1897 /* init variables: */
1898 offset = target - gfrom;
1899 mycolor = board[gfrom]&1;
1900
1901 /* loop until we hit the edge of the board, or another piece: */
1902 do {
1903 /* case when the target is an empty square: */
1904 if (board[target] == npiece) {
1905 if (!captures) {
1906 add_move(target, 0);
1907 }
1908 target += offset;
1909 }
1910
1911 /* case when an enemy piece is hit: */
1912 else if ((board[target]&1) != mycolor) {
1913 add_capture(target, board[target], 0, FALSE);
1914 break;
1915 }
1916
1917 /* otherwise, we have hit a friendly piece (or edge of board): */
1918 else
1919 break;
1920 } while (board[target] != frame);
1921
1922 /* we have finished generating all of the sliding moves, so return: */
1923 return;
1924
1925 }
1926
1927
unmake(move_s moves[],int i)1928 void unmake (move_s moves[], int i) {
1929
1930 /* un-make a move */
1931
1932 /* rather than writing out from[i].from, from[i].target, etc. all over
1933 the place, just make a copy of them here: */
1934 int ep, from, target, captured, promoted, castled;
1935 ep = moves[i].ep;
1936 from = moves[i].from;
1937 target = moves[i].target;
1938 captured = moves[i].captured;
1939 promoted = moves[i].promoted;
1940 castled = moves[i].castled;
1941
1942 //if ((moves[i].target == 0) || ((moves[i].target != 0) && (board[moves[i].target] == npiece)))
1943 // DIE;
1944
1945 ply--;
1946
1947 //printf("%d ", ply);
1948
1949 ep_square = path_x[ply].epsq;
1950
1951 /* update the 50 move info: */
1952 fifty = path_x[ply].fifty;
1953
1954 if (from == 0) /* drop move */
1955 {
1956 /* Drop moves are hanled fully seperate because we exepect to encouter
1957 lots of them and we try to skip as many checks as possible.
1958 Note that the critical path for drop moves is very short.
1959 Also, we have to handle pieces[] and squares[] specially */
1960
1961 /* remove from piece array, unset piece-square pointer */
1962
1963 pieces[squares[target]] = 0;
1964 is_promoted[squares[target]] = path_x[ply].was_promoted;
1965
1966 /* unset square->piece pointer */
1967 squares[target] = 0;
1968 // moved[target] = 0;
1969
1970 piece_count--;
1971
1972 assert(promoted < npiece && promoted > frame);
1973
1974 DropaddHolding(promoted, NotToMove);
1975
1976 RemoveMaterial(promoted);
1977
1978 /* restore board, either no piece or ep square */
1979 board[target] = captured;
1980
1981 Hash(promoted,target);
1982
1983 white_to_move ^= 1;
1984
1985 return;
1986 }
1987 else
1988 {
1989
1990 /* update the "general" pieces[] / squares[] info (special moves need
1991 special handling later): */
1992
1993 squares[from] = squares[target];
1994 squares[target] = path_x[ply].cap_num;
1995 pieces[squares[target]] = target;
1996 pieces[squares[from]] = from;
1997
1998 is_promoted[squares[target]] = path_x[ply].was_promoted;
1999
2000 /* update the piece count for determining opening/middlegame/endgame stage */
2001 if (!ep)
2002 {
2003 switch (captured) {
2004 case (npiece): break;
2005 default:
2006
2007 if (Variant == Bughouse || Variant == Crazyhouse)
2008 {
2009 if (is_promoted[squares[target]])
2010 {
2011 removeHolding(SwitchPromoted(captured), NotToMove);
2012 }
2013 else
2014 {
2015 removeHolding(SwitchColor(captured), NotToMove);
2016 }
2017 }
2018
2019 Hash(captured, target);
2020
2021 AddMaterial(captured);
2022
2023 piece_count++;
2024 break;
2025 }
2026 }
2027
2028 /* white pawn moves: */
2029 if (board[target] == wpawn) {
2030 /* look for an en passant move: */
2031 if (ep) {
2032
2033 Hash(wpawn, target);
2034 Hash(wpawn, from);
2035 Hash(bpawn, target-12);
2036
2037 board[target] = npiece;
2038 board[from] = wpawn;
2039
2040 AddMaterial(bpawn);
2041
2042 removeHolding(wpawn, WHITE);
2043 piece_count++;
2044
2045 board[target-12] = bpawn;
2046 moved[target]--;
2047 moved[from]--;
2048 moved[target-12]--;
2049 white_to_move ^= 1;
2050 squares[target-12] = path_x[ply].cap_num;
2051 pieces[path_x[ply].cap_num] = target-12;
2052 squares[target] = 0;
2053 return;
2054 }
2055
2056 /* otherwise, we have a "regular" pawn move: */
2057 Hash(wpawn, from);
2058 Hash(wpawn, target);
2059
2060 board[target] = captured;
2061 board[from] = wpawn;
2062 moved[target]--;
2063 moved[from]--;
2064 white_to_move ^= 1;
2065 return;
2066
2067 }
2068
2069 /* black pawn moves: */
2070 if (board[target] == bpawn) {
2071 /* look for an en passant move: */
2072 if (ep) {
2073
2074 Hash(bpawn, target);
2075 Hash(bpawn, from);
2076 Hash(wpawn, target+12);
2077
2078 board[target] = npiece;
2079 board[from] = bpawn;
2080
2081 AddMaterial(wpawn);
2082
2083 removeHolding(bpawn, BLACK);
2084 piece_count++;
2085
2086 board[target+12] = wpawn;
2087 moved[target]--;
2088 moved[from]--;
2089 moved[target+12]--;
2090 white_to_move ^= 1;
2091 squares[target+12] = path_x[ply].cap_num;
2092 pieces[path_x[ply].cap_num] = target+12;
2093 squares[target] = 0;
2094 return;
2095 }
2096
2097 Hash(bpawn, from);
2098 Hash(bpawn, target);
2099
2100 /* otherwise, we have a "regular" pawn move: */
2101 board[target] = captured;
2102 board[from] = bpawn;
2103 moved[target]--;
2104 moved[from]--;
2105 white_to_move ^= 1;
2106 return;
2107
2108 }
2109
2110 /* piece moves, other than the king: */
2111 if (board[target] != wking && board[target] != bking && !promoted) {
2112 board[from] = board[target];
2113 board[target] = captured;
2114 moved[target]--;
2115 moved[from]--;
2116 white_to_move ^= 1;
2117
2118 Hash(board[from], target);
2119 Hash(board[from], from);
2120
2121 return;
2122 }
2123
2124 /* look for a promotion move: */
2125 if (promoted) {
2126 /* white promotions: */
2127 if (board[target]%2) {
2128 board[target] = captured;
2129 board[from] = wpawn;
2130 moved[target]--;
2131 moved[from]--;
2132 white_to_move ^= 1;
2133
2134 Hash(wpawn, from);
2135 Hash(promoted, target);
2136
2137 RemoveMaterial(promoted);
2138 AddMaterial(wpawn);
2139
2140 return;
2141 }
2142
2143 /* black promotions: */
2144 board[target] = captured;
2145 board[from] = bpawn;
2146 moved[target]--;
2147 moved[from]--;
2148 white_to_move ^= 1;
2149
2150 Hash(bpawn, from);
2151 Hash(promoted, target);
2152
2153 RemoveMaterial(promoted);
2154 AddMaterial(bpawn);
2155
2156 return;
2157 }
2158
2159 /* otherwise, we have a king move of some kind: */
2160 /* White king moves first: */
2161 if (board[target] == wking) {
2162 /* record the new white king location: */
2163 wking_loc = from;
2164
2165 /* perform the white king's move: */
2166 board[target] = captured;
2167 board[from] = wking;
2168 moved[target]--;
2169 moved[from]--;
2170 white_to_move ^= 1;
2171
2172 Hash(wking, from);
2173 Hash(wking, target);
2174
2175 /* check for castling: */
2176 /* check for white kingside castling: */
2177 if (castled == wck) {
2178 board[33] = wrook;
2179 board[31] = npiece;
2180 moved[33]--;
2181 moved[31]--;
2182 white_castled = no_castle;
2183 squares[33] = squares[31];
2184 squares[31] = 0;
2185 pieces[squares[33]] = 33;
2186
2187 Hash(wrook, 33);
2188 Hash(wrook, 31);
2189
2190 return;
2191 }
2192
2193 /* check for white queenside castling: */
2194 else if (castled == wcq) {
2195 board[26] = wrook;
2196 board[29] = npiece;
2197 moved[26]--;
2198 moved[29]--;
2199 white_castled = no_castle;
2200 squares[26] = squares[29];
2201 squares[29] = 0;
2202 pieces[squares[26]] = 26;
2203
2204 Hash(wrook, 29);
2205 Hash(wrook, 26);
2206
2207 return;
2208 }
2209
2210 return;
2211 }
2212
2213 /* now we have only black king moves left: */
2214 else {
2215 /* record the new black king location: */
2216 bking_loc = from;
2217
2218 /* perform the black king's move: */
2219 board[target] = captured;
2220 board[from] = bking;
2221 moved[target]--;
2222 moved[from]--;
2223 white_to_move ^= 1;
2224
2225 Hash(bking, from);
2226 Hash(bking, target);
2227
2228 /* check for castling: */
2229 /* check for black kingside castling: */
2230 if (castled == bck) {
2231 board[117] = brook;
2232 board[115] = npiece;
2233 moved[117]--;
2234 moved[115]--;
2235 black_castled = no_castle;
2236 squares[117] = squares[115];
2237 squares[115] = 0;
2238 pieces[squares[117]] = 117;
2239
2240 Hash(brook, 117);
2241 Hash(brook, 115);
2242
2243 return;
2244 }
2245
2246 /* check for black queenside castling: */
2247 else if (castled == bcq) {
2248 board[110] = brook;
2249 board[113] = npiece;
2250 moved[110]--;
2251 moved[113]--;
2252 black_castled = no_castle;
2253 squares[110] = squares[113];
2254 squares[113] = 0;
2255 pieces[squares[110]] = 110;
2256
2257 Hash(brook, 110);
2258 Hash(brook, 113);
2259
2260 return;
2261 }
2262 }
2263 }
2264 return;
2265 }
2266