| 537 candidates[candidatecount].piece = gamestate->board[r][f]; |
537 candidates[candidatecount].piece = gamestate->board[r][f]; |
| 538 candidates[candidatecount].fromrow = r; |
538 candidates[candidatecount].fromrow = r; |
| 539 candidates[candidatecount].fromfile = f; |
539 candidates[candidatecount].fromfile = f; |
| 540 candidates[candidatecount].torow = row; |
540 candidates[candidatecount].torow = row; |
| 541 candidates[candidatecount].tofile = file; |
541 candidates[candidatecount].tofile = file; |
| |
542 if ((gamestate->board[r][f]&PIECE_MASK) == PAWN |
| |
543 && (row == 0 || row == 7)) { |
| |
544 /* the exact piece for promotion does not matter */ |
| |
545 candidates[candidatecount].promotion = color|QUEEN; |
| |
546 } |
| 542 candidatecount++; |
547 candidatecount++; |
| 543 |
548 |
| 544 /* capturing move */ |
549 /* capturing move */ |
| 545 memcpy(&(candidates[candidatecount]), |
550 memcpy(&(candidates[candidatecount]), |
| 546 &(candidates[candidatecount-1]), sizeof(Move)); |
551 &(candidates[candidatecount-1]), sizeof(Move)); |
| 641 uint8_t piece = move->piece & PIECE_MASK; |
646 uint8_t piece = move->piece & PIECE_MASK; |
| 642 bool incheck = gamestate->movecount > 0 ? last_move(gamestate).check:false; |
647 bool incheck = gamestate->movecount > 0 ? last_move(gamestate).check:false; |
| 643 |
648 |
| 644 Move threats[16], *threat = NULL; |
649 Move threats[16], *threat = NULL; |
| 645 uint8_t threatcount; |
650 uint8_t threatcount; |
| 646 |
651 |
| 647 if (get_threats(gamestate, move->torow, move->tofile, color, |
652 if (get_threats(gamestate, move->torow, move->tofile, color, |
| 648 threats, &threatcount)) { |
653 threats, &threatcount)) { |
| 649 |
654 |
| 650 int reason = INVALID_POSITION; |
655 int reason = INVALID_POSITION; |
| 651 |
656 |
| 652 /* find threats for the specified position */ |
657 /* find threats for the specified position */ |
| 653 for (uint8_t i = 0 ; i < threatcount ; i++) { |
658 for (uint8_t i = 0 ; i < threatcount ; i++) { |
| 654 if ((threats[i].piece & PIECE_MASK) == piece |
659 if (threats[i].piece == move->piece && |
| 655 && (threats[i].piece & COLOR_MASK) == color && |
|
| 656 (move->fromrow == POS_UNSPECIFIED || |
660 (move->fromrow == POS_UNSPECIFIED || |
| 657 move->fromrow == threats[i].fromrow) && |
661 move->fromrow == threats[i].fromrow) && |
| 658 (move->fromfile == POS_UNSPECIFIED || |
662 (move->fromfile == POS_UNSPECIFIED || |
| 659 move->fromfile == threats[i].fromfile)) { |
663 move->fromfile == threats[i].fromfile)) { |
| 660 |
664 |
| 661 if (threat) { |
665 if (threat) { |
| 662 return AMBIGUOUS_MOVE; |
666 return AMBIGUOUS_MOVE; |
| 663 } else { |
667 } else { |
| 664 /* found threat is no real threat */ |
668 /* found threat is no real threat */ |
| |
669 // TODO: why didn't we call get_real_threats() ? |
| 665 if (is_pinned(gamestate, &(threats[i]))) { |
670 if (is_pinned(gamestate, &(threats[i]))) { |
| 666 reason = incheck?KING_IN_CHECK: |
671 reason = incheck?KING_IN_CHECK: |
| 667 (piece==KING?KING_MOVES_INTO_CHECK:PIECE_PINNED); |
672 (piece==KING?KING_MOVES_INTO_CHECK:PIECE_PINNED); |
| 668 } else { |
673 } else { |
| 669 threat = &(threats[i]); |
674 threat = &(threats[i]); |
| 675 /* can't threaten specified position */ |
680 /* can't threaten specified position */ |
| 676 if (!threat) { |
681 if (!threat) { |
| 677 return reason; |
682 return reason; |
| 678 } |
683 } |
| 679 |
684 |
| 680 memcpy(move, threat, sizeof(Move)); |
685 /* found a threat, copy the source location */ |
| |
686 move->fromrow = threat->fromrow; |
| |
687 move->fromfile = threat->fromfile; |
| 681 return VALID_MOVE_SYNTAX; |
688 return VALID_MOVE_SYNTAX; |
| 682 } else { |
689 } else { |
| 683 return INVALID_POSITION; |
690 return INVALID_POSITION; |
| 684 } |
691 } |
| 685 } |
692 } |