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 28uint32_t total_moves; 29uint32_t total_movegens; 30 31int numb_moves; 32static move_s *genfor; 33 34int fcaptures; 35int gfrom; 36 37int kingcap; /* break if we capture the king */ 38 39bool 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 453void 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 470restart: 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 793bool 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 814bool 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 1225int 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 1292void 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 is_promoted[find_slot] = 0; 1345 1346 /* set square->piece pointer */ 1347 squares[target] = find_slot; 1348 // moved[target] = 1; 1349 1350 //if (promoted <= frame || promoted >= npiece) 1351 // DIE; 1352 1353 assert(promoted > frame && promoted < npiece); 1354 1355 DropremoveHolding(promoted, ToMove); 1356 1357 /* piece went off holding but onto board */ 1358 AddMaterial(promoted); 1359 1360 /* put our piece on the board */ 1361 board[target] = promoted; 1362 1363 Hash(promoted,target); 1364 1365 white_to_move ^= 1; 1366 ply++; 1367 1368 return; 1369 } 1370 else 1371 { 1372 1373 1374 /* update the "general" pieces[] / squares[] info (special moves need 1375 special handling later): */ 1376 path_x[ply].cap_num = squares[target]; 1377 path_x[ply].was_promoted = is_promoted[squares[target]]; 1378 pieces[squares[target]] = 0; 1379 pieces[squares[from]] = target; 1380 squares[target] = squares[from]; 1381 squares[from] = 0; 1382 1383 /* update the piece count & add Holdings */ 1384 if (!ep) 1385 { 1386 switch (board[target]) { 1387 case (npiece): break; 1388 default: 1389 1390 if (Variant == Bughouse || Variant == Crazyhouse) 1391 { 1392 if (path_x[ply].was_promoted) 1393 { 1394 addHolding(SwitchPromoted(board[target]), ToMove); 1395 } 1396 else 1397 { 1398 addHolding(SwitchColor(board[target]), ToMove); 1399 } 1400 } 1401 1402 RemoveMaterial(board[target]); 1403 1404 /* remove captured piece */ 1405 Hash(board[target], target); 1406 1407 piece_count--; 1408 break; 1409 } 1410 } 1411 1412 /* white pawn moves: */ 1413 if (board[from] == wpawn) { 1414 /* look for a promotion move: */ 1415 if (promoted) { 1416 board[target] = promoted; 1417 board[from] = npiece; 1418 moved[target]++; 1419 moved[from]++; 1420 white_to_move ^= 1; 1421 1422 is_promoted[squares[target]] = 1; 1423 1424 /* remove pawn */ 1425 Hash(wpawn, from); 1426 /* add new stuff */ 1427 Hash(promoted, target); 1428 1429 RemoveMaterial(wpawn); 1430 AddMaterial(promoted); 1431 1432 ply++; 1433 1434 return; 1435 } 1436 1437 /* look for an en passant move: */ 1438 if (ep) { 1439 1440 /* remove pawn */ 1441 Hash(wpawn, from); 1442 /* remove ep pawn */ 1443 Hash(bpawn, target-12); 1444 /* add target pawn */ 1445 Hash(wpawn, target); 1446 1447 RemoveMaterial(bpawn); 1448 1449 board[target] = wpawn; 1450 board[from] = npiece; 1451 1452 addHolding(wpawn, WHITE); 1453 piece_count--; 1454 1455 board[target-12] = npiece; 1456 moved[target]++; 1457 moved[from]++; 1458 moved[target-12]++; 1459 white_to_move ^= 1; 1460 path_x[ply].cap_num = squares[target-12]; 1461 path_x[ply].was_promoted = 0; 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 path_x[ply].was_promoted = 0; 1541 pieces[squares[target+12]] = 0; 1542 squares[target+12] = 0; 1543 1544 ply++; 1545 1546 return; 1547 } 1548 1549 /* otherwise, we have a "regular" pawn move: */ 1550 /* first check to see if we've moved a pawn down 2 squares: */ 1551 if (target == from-24) 1552 ep_square = from-12; 1553 1554 board[target] = bpawn; 1555 board[from] = npiece; 1556 moved[target]++; 1557 moved[from]++; 1558 white_to_move ^= 1; 1559 1560 Hash(bpawn, from); 1561 Hash(bpawn, target); 1562 1563 ply++; 1564 1565 return; 1566 } 1567 1568 /* piece moves, other than the king: */ 1569 if (board[from] != wking && board[from] != bking) { 1570 1571 Hash(board[from], from); 1572 Hash(board[from], target); 1573 1574 board[target] = board[from]; 1575 board[from] = npiece; 1576 moved[target]++; 1577 moved[from]++; 1578 white_to_move ^= 1; 1579 1580 ply++; 1581 1582 return; 1583 } 1584 1585 /* otherwise, we have a king move of some kind: */ 1586 /* White king moves first: */ 1587 if (board[from] == wking) { 1588 /* record the new white king location: */ 1589 wking_loc = target; 1590 1591 /* perform the white king's move: */ 1592 board[target] = wking; 1593 board[from] = npiece; 1594 moved[target]++; 1595 moved[from]++; 1596 white_to_move ^= 1; 1597 1598 Hash(wking, from); 1599 Hash(wking, target); 1600 1601 /* check for castling: */ 1602 /* check for white kingside castling: */ 1603 if (castled == wck) { 1604 board[33] = npiece; 1605 board[31] = wrook; 1606 moved[33]++; 1607 moved[31]++; 1608 white_castled = wck; 1609 pieces[squares[33]] = 31; 1610 squares[31] = squares[33]; 1611 squares[33] = 0; 1612 1613 Hash(wrook, 33); 1614 Hash(wrook, 31); 1615 1616 ply++; 1617 1618 return; 1619 } 1620 1621 /* check for white queenside castling: */ 1622 else if (castled == wcq) { 1623 board[26] = npiece; 1624 board[29] = wrook; 1625 moved[26]++; 1626 moved[29]++; 1627 white_castled = wcq; 1628 pieces[squares[26]] = 29; 1629 squares[29] = squares[26]; 1630 squares[26] = 0; 1631 1632 Hash(wrook, 26); 1633 Hash(wrook, 29); 1634 1635 ply++; 1636 1637 return; 1638 } 1639 1640 ply++; 1641 1642 return; 1643 } 1644 1645 /* now we have only black king moves left: */ 1646 else { 1647 /* record the new black king location: */ 1648 bking_loc = target; 1649 1650 /* perform the black king's move: */ 1651 board[target] = bking; 1652 board[from] = npiece; 1653 moved[target]++; 1654 moved[from]++; 1655 white_to_move ^= 1; 1656 1657 Hash(bking, from); 1658 Hash(bking, target); 1659 1660 /* check for castling: */ 1661 /* check for black kingside castling: */ 1662 if (castled == bck) { 1663 board[117] = npiece; 1664 board[115] = brook; 1665 moved[117]++; 1666 moved[115]++; 1667 black_castled = bck; 1668 pieces[squares[117]] = 115; 1669 squares[115] = squares[117]; 1670 squares[117] = 0; 1671 1672 Hash(brook, 117); 1673 Hash(brook, 115); 1674 1675 ply++; 1676 1677 return; 1678 } 1679 1680 /* check for black queenside castling: */ 1681 else if (castled == bcq) { 1682 board[110] = npiece; 1683 board[113] = brook; 1684 moved[110]++; 1685 moved[113]++; 1686 black_castled = bcq; 1687 pieces[squares[110]] = 113; 1688 squares[113] = squares[110]; 1689 squares[110] = 0; 1690 1691 Hash(brook, 110); 1692 Hash(brook, 113); 1693 1694 ply++; 1695 1696 return; 1697 } 1698 } 1699 ply++; 1700 1701 return; 1702 } 1703} 1704 1705void add_move(int Ptarget, 1706 int Ppromoted) 1707{ 1708 genfor[numb_moves].from = gfrom; 1709 genfor[numb_moves].target = Ptarget; 1710 genfor[numb_moves].captured = npiece; 1711 genfor[numb_moves].castled = no_castle; 1712 genfor[numb_moves].promoted = Ppromoted; 1713 genfor[numb_moves].ep = FALSE; 1714 numb_moves++; 1715 1716 return; 1717} 1718 1719void add_capture(int Ptarget, 1720 int Pcaptured, 1721 int Ppromoted, 1722 int Pep) 1723{ 1724 if ((Variant != Suicide) && (Pcaptured == wking || Pcaptured == bking)) 1725 { 1726 kingcap = TRUE; 1727 return; 1728 } 1729 else 1730 if (Pcaptured != npiece) fcaptures = TRUE; 1731 1732 genfor[numb_moves].from = gfrom; 1733 genfor[numb_moves].target = Ptarget; 1734 genfor[numb_moves].captured = Pcaptured; 1735 genfor[numb_moves].castled = no_castle; 1736 genfor[numb_moves].promoted = Ppromoted; 1737 genfor[numb_moves].ep = Pep; 1738 numb_moves++; 1739 1740 return; 1741} 1742 1743void try_drop (int ptype) 1744{ 1745 genfor[numb_moves].from = 0; 1746 genfor[numb_moves].target = gfrom; 1747 genfor[numb_moves].captured = npiece; 1748 genfor[numb_moves].castled = no_castle; 1749 genfor[numb_moves].promoted = ptype; 1750 genfor[numb_moves].ep = FALSE; 1751 numb_moves++; 1752 1753 return; 1754} 1755 1756void push_king_castle (int Ptarget, int Pcastle_type) 1757{ 1758 genfor[numb_moves].from = gfrom; 1759 genfor[numb_moves].target = Ptarget; 1760 genfor[numb_moves].captured = npiece; 1761 genfor[numb_moves].castled = Pcastle_type; 1762 genfor[numb_moves].promoted = 0; 1763 genfor[numb_moves].ep = FALSE; 1764 numb_moves++; 1765 1766 return; 1767} 1768 1769void push_king (int target) { 1770 1771 /* add king moves to the moves array */ 1772 1773 /* first see if the move will take the king off the board: */ 1774 if (board[target] == frame) 1775 return; 1776 1777 /* check to see if we have a non capture when in qsearch: */ 1778 if (board[target] == npiece && captures) 1779 return; 1780 1781 /* non-capture, 'normal' king moves: */ 1782 if (board[target] == npiece) { 1783 add_move(target, 0); 1784 return; 1785 } 1786 1787 /* 'normal' capture moves by the king: */ 1788 else if ((board[target]&1) != (board[gfrom]&1)) { 1789 add_capture(target, board[target], 0, FALSE); 1790 return; 1791 } 1792 1793 /* no more possible moves for the king, so return: */ 1794 return; 1795} 1796 1797 1798void push_knighT (int target) { 1799 1800 /* add knight moves to the moves array */ 1801 1802 /* check to see if we have a non capture when in qsearch: */ 1803 if (board[target] == npiece && captures) 1804 return; 1805 1806 /* check for a non-capture knight move: */ 1807 if (board[target] == npiece) { 1808 add_move(target, 0); 1809 return; 1810 } 1811 1812 /* check for a capture knight move: */ 1813 else if ((board[target]&1) != (board[gfrom]&1)) { 1814 add_capture(target, board[target], 0, FALSE); 1815 return; 1816 } 1817 1818 /* no more possible moves left for the knight, so return: */ 1819 return; 1820} 1821 1822 1823void push_pawn (int target, bool is_ep) { 1824 1825 /* add pawn moves to the moves array */ 1826 1827 int captured_piece; 1828 1829 /* check to see if it's an ep move: */ 1830 if (is_ep) { 1831 if (board[gfrom] == wpawn) { 1832 add_capture(target, bpawn, 0, TRUE); 1833 return; 1834 } 1835 else { 1836 add_capture(target, wpawn, 0, TRUE); 1837 return; 1838 } 1839 } 1840 1841 /* record which piece we are taking, so we don't have to compute it over 1842 and over again: */ 1843 captured_piece = board[target]; 1844 1845 /* look for a white promotion move: */ 1846 if (board[gfrom] == wpawn && rank(gfrom) == 7) { 1847 add_capture(target, captured_piece, wqueen, FALSE); 1848 add_capture(target, captured_piece, wrook, FALSE); 1849 add_capture(target, captured_piece, wbishop, FALSE); 1850 add_capture(target, captured_piece, wknight, FALSE); 1851 if (Variant == Suicide) 1852 add_capture(target, captured_piece, wking, FALSE); 1853 /* we've finished generating all the promotions: */ 1854 return; 1855 } 1856 1857 /* look for a black promotion move: */ 1858 else if (board[gfrom] == bpawn && rank(gfrom) == 2) { 1859 add_capture(target, captured_piece, bqueen, FALSE); 1860 add_capture(target, captured_piece, brook, FALSE); 1861 add_capture(target, captured_piece, bbishop, FALSE); 1862 add_capture(target, captured_piece, bknight, FALSE); 1863 if (Variant == Suicide) 1864 add_capture(target, captured_piece, bking, FALSE); 1865 /* we've finished generating all the promotions: */ 1866 return; 1867 } 1868 1869 /* otherwise, we have a normal pawn move: */ 1870 else { 1871 add_capture(target, captured_piece, 0, FALSE); 1872 return; 1873 } 1874 1875 /* the function should never get here, but just for completeness: */ 1876 return; 1877} 1878 1879void push_pawn_simple (int target) { 1880 1881 /* add pawn moves to the moves array */ 1882 1883 add_move(target, 0); 1884 return; 1885} 1886 1887void push_slidE (int target) { 1888 1889 /* add moves for sliding pieces to the moves array */ 1890 1891 int offset; 1892 int mycolor; 1893 1894 /* check to see if we have gone off the board first: */ 1895// if (board[target] == frame) 1896 // return; 1897 1898 /* init variables: */ 1899 offset = target - gfrom; 1900 mycolor = board[gfrom]&1; 1901 1902 /* loop until we hit the edge of the board, or another piece: */ 1903 do { 1904 /* case when the target is an empty square: */ 1905 if (board[target] == npiece) { 1906 if (!captures) { 1907 add_move(target, 0); 1908 } 1909 target += offset; 1910 } 1911 1912 /* case when an enemy piece is hit: */ 1913 else if ((board[target]&1) != mycolor) { 1914 add_capture(target, board[target], 0, FALSE); 1915 break; 1916 } 1917 1918 /* otherwise, we have hit a friendly piece (or edge of board): */ 1919 else 1920 break; 1921 } while (board[target] != frame); 1922 1923 /* we have finished generating all of the sliding moves, so return: */ 1924 return; 1925 1926} 1927 1928 1929void unmake (move_s moves[], int i) { 1930 1931 /* un-make a move */ 1932 1933 /* rather than writing out from[i].from, from[i].target, etc. all over 1934 the place, just make a copy of them here: */ 1935 int ep, from, target, captured, promoted, castled; 1936 ep = moves[i].ep; 1937 from = moves[i].from; 1938 target = moves[i].target; 1939 captured = moves[i].captured; 1940 promoted = moves[i].promoted; 1941 castled = moves[i].castled; 1942 1943 //if ((moves[i].target == 0) || ((moves[i].target != 0) && (board[moves[i].target] == npiece))) 1944 // DIE; 1945 1946 ply--; 1947 1948//printf("%d ", ply); 1949 1950 ep_square = path_x[ply].epsq; 1951 1952 /* update the 50 move info: */ 1953 fifty = path_x[ply].fifty; 1954 1955 if (from == 0) /* drop move */ 1956 { 1957 /* Drop moves are hanled fully seperate because we exepect to encouter 1958 lots of them and we try to skip as many checks as possible. 1959 Note that the critical path for drop moves is very short. 1960 Also, we have to handle pieces[] and squares[] specially */ 1961 1962 /* remove from piece array, unset piece-square pointer */ 1963 1964 pieces[squares[target]] = 0; 1965 assert(is_promoted[squares[target]] == 0); 1966 1967 /* unset square->piece pointer */ 1968 squares[target] = 0; 1969 // moved[target] = 0; 1970 1971 piece_count--; 1972 1973 assert(promoted < npiece && promoted > frame); 1974 1975 DropaddHolding(promoted, NotToMove); 1976 1977 RemoveMaterial(promoted); 1978 1979 /* restore board, either no piece or ep square */ 1980 board[target] = captured; 1981 1982 Hash(promoted,target); 1983 1984 white_to_move ^= 1; 1985 1986 return; 1987 } 1988 else 1989 { 1990 1991 /* update the "general" pieces[] / squares[] info (special moves need 1992 special handling later): */ 1993 1994 squares[from] = squares[target]; 1995 squares[target] = path_x[ply].cap_num; 1996 is_promoted[squares[target]] = path_x[ply].was_promoted; 1997 pieces[squares[target]] = target; 1998 pieces[squares[from]] = from; 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 is_promoted[path_x[ply].cap_num] = path_x[ply].was_promoted; 2052 pieces[path_x[ply].cap_num] = target-12; 2053 squares[target] = 0; 2054 return; 2055 } 2056 2057 /* otherwise, we have a "regular" pawn move: */ 2058 Hash(wpawn, from); 2059 Hash(wpawn, target); 2060 2061 board[target] = captured; 2062 board[from] = wpawn; 2063 moved[target]--; 2064 moved[from]--; 2065 white_to_move ^= 1; 2066 return; 2067 2068 } 2069 2070 /* black pawn moves: */ 2071 if (board[target] == bpawn) { 2072 /* look for an en passant move: */ 2073 if (ep) { 2074 2075 Hash(bpawn, target); 2076 Hash(bpawn, from); 2077 Hash(wpawn, target+12); 2078 2079 board[target] = npiece; 2080 board[from] = bpawn; 2081 2082 AddMaterial(wpawn); 2083 2084 removeHolding(bpawn, BLACK); 2085 piece_count++; 2086 2087 board[target+12] = wpawn; 2088 moved[target]--; 2089 moved[from]--; 2090 moved[target+12]--; 2091 white_to_move ^= 1; 2092 squares[target+12] = path_x[ply].cap_num; 2093 is_promoted[path_x[ply].cap_num] = path_x[ply].was_promoted; 2094 pieces[path_x[ply].cap_num] = target+12; 2095 squares[target] = 0; 2096 return; 2097 } 2098 2099 Hash(bpawn, from); 2100 Hash(bpawn, target); 2101 2102 /* otherwise, we have a "regular" pawn move: */ 2103 board[target] = captured; 2104 board[from] = bpawn; 2105 moved[target]--; 2106 moved[from]--; 2107 white_to_move ^= 1; 2108 return; 2109 2110 } 2111 2112 /* piece moves, other than the king: */ 2113 if (board[target] != wking && board[target] != bking && !promoted) { 2114 board[from] = board[target]; 2115 board[target] = captured; 2116 moved[target]--; 2117 moved[from]--; 2118 white_to_move ^= 1; 2119 2120 Hash(board[from], target); 2121 Hash(board[from], from); 2122 2123 return; 2124 } 2125 2126 /* look for a promotion move: */ 2127 if (promoted) { 2128 /* white promotions: */ 2129 if (board[target]%2) { 2130 board[target] = captured; 2131 board[from] = wpawn; 2132 moved[target]--; 2133 moved[from]--; 2134 white_to_move ^= 1; 2135 2136 is_promoted[squares[from]] = 0; 2137 2138 Hash(wpawn, from); 2139 Hash(promoted, target); 2140 2141 RemoveMaterial(promoted); 2142 AddMaterial(wpawn); 2143 2144 return; 2145 } 2146 2147 /* black promotions: */ 2148 board[target] = captured; 2149 board[from] = bpawn; 2150 moved[target]--; 2151 moved[from]--; 2152 white_to_move ^= 1; 2153 2154 is_promoted[squares[from]] = 0; 2155 2156 Hash(bpawn, from); 2157 Hash(promoted, target); 2158 2159 RemoveMaterial(promoted); 2160 AddMaterial(bpawn); 2161 2162 return; 2163 } 2164 2165 /* otherwise, we have a king move of some kind: */ 2166 /* White king moves first: */ 2167 if (board[target] == wking) { 2168 /* record the new white king location: */ 2169 wking_loc = from; 2170 2171 /* perform the white king's move: */ 2172 board[target] = captured; 2173 board[from] = wking; 2174 moved[target]--; 2175 moved[from]--; 2176 white_to_move ^= 1; 2177 2178 Hash(wking, from); 2179 Hash(wking, target); 2180 2181 /* check for castling: */ 2182 /* check for white kingside castling: */ 2183 if (castled == wck) { 2184 board[33] = wrook; 2185 board[31] = npiece; 2186 moved[33]--; 2187 moved[31]--; 2188 white_castled = no_castle; 2189 squares[33] = squares[31]; 2190 squares[31] = 0; 2191 pieces[squares[33]] = 33; 2192 2193 Hash(wrook, 33); 2194 Hash(wrook, 31); 2195 2196 return; 2197 } 2198 2199 /* check for white queenside castling: */ 2200 else if (castled == wcq) { 2201 board[26] = wrook; 2202 board[29] = npiece; 2203 moved[26]--; 2204 moved[29]--; 2205 white_castled = no_castle; 2206 squares[26] = squares[29]; 2207 squares[29] = 0; 2208 pieces[squares[26]] = 26; 2209 2210 Hash(wrook, 29); 2211 Hash(wrook, 26); 2212 2213 return; 2214 } 2215 2216 return; 2217 } 2218 2219 /* now we have only black king moves left: */ 2220 else { 2221 /* record the new black king location: */ 2222 bking_loc = from; 2223 2224 /* perform the black king's move: */ 2225 board[target] = captured; 2226 board[from] = bking; 2227 moved[target]--; 2228 moved[from]--; 2229 white_to_move ^= 1; 2230 2231 Hash(bking, from); 2232 Hash(bking, target); 2233 2234 /* check for castling: */ 2235 /* check for black kingside castling: */ 2236 if (castled == bck) { 2237 board[117] = brook; 2238 board[115] = npiece; 2239 moved[117]--; 2240 moved[115]--; 2241 black_castled = no_castle; 2242 squares[117] = squares[115]; 2243 squares[115] = 0; 2244 pieces[squares[117]] = 117; 2245 2246 Hash(brook, 117); 2247 Hash(brook, 115); 2248 2249 return; 2250 } 2251 2252 /* check for black queenside castling: */ 2253 else if (castled == bcq) { 2254 board[110] = brook; 2255 board[113] = npiece; 2256 moved[110]--; 2257 moved[113]--; 2258 black_castled = no_castle; 2259 squares[110] = squares[113]; 2260 squares[113] = 0; 2261 pieces[squares[110]] = 110; 2262 2263 Hash(brook, 110); 2264 Hash(brook, 113); 2265 2266 return; 2267 } 2268 } 2269 } 2270 return; 2271} 2272