| 136 } |
136 } |
| 137 } else if (piece_type(move->piece) != KING) { |
137 } else if (piece_type(move->piece) != KING) { |
| 138 /* resolve ambiguities, if any */ |
138 /* resolve ambiguities, if any */ |
| 139 Move candidates[16]; |
139 Move candidates[16]; |
| 140 size_t ccount; |
140 size_t ccount; |
| 141 if (get_candidates(gamestate, move->torow, move->tofile, |
141 if (get_real_candidates(gamestate, move->torow, move->tofile, |
| 142 piece_color(move->piece), candidates, &ccount)) { |
142 piece_color(move->piece), candidates, &ccount)) { |
| 143 unsigned int ambrows = 0, ambfiles = 0, ambpiece = 0; |
143 unsigned int ambrows = 0, ambfiles = 0, ambpiece = 0; |
| 144 for (size_t i = 0 ; i < ccount ; i++) { |
144 for (size_t i = 0 ; i < ccount ; i++) { |
| 145 // TODO: check if we need to discard pinned pieces here |
|
| 146 if (candidates[i].piece == move->piece) { |
145 if (candidates[i].piece == move->piece) { |
| 147 ambpiece++; |
146 ambpiece++; |
| 148 if (candidates[i].fromrow == move->fromrow) { |
147 if (candidates[i].fromrow == move->fromrow) { |
| 149 ambrows++; |
148 ambrows++; |
| 150 } |
149 } |
| 666 |
665 |
| 667 bool get_threats(const GameState *gamestate, Row row, File file, |
666 bool get_threats(const GameState *gamestate, Row row, File file, |
| 668 Color color, Move *threats, size_t *threatcount) { |
667 Color color, Move *threats, size_t *threatcount) { |
| 669 |
668 |
| 670 /* simulate a capturing move on the target position */ |
669 /* simulate a capturing move on the target position */ |
| 671 // TODO: this does NOT disregard the pin, as stated in the spec! |
|
| 672 Color opcolor = opponent_color(color); |
670 Color opcolor = opponent_color(color); |
| 673 GameState simulation = gamestate_copy_sim(gamestate); |
671 GameState simulation = gamestate_copy_sim(gamestate); |
| 674 if (piece_color(piece_at(&simulation, row, file)) != opcolor) { |
672 if (piece_color(piece_at(&simulation, row, file)) != opcolor) { |
| 675 /* set a fake pawn if the field is not occupied by the opponent */ |
673 /* set a fake pawn if the field is not occupied by the opponent */ |
| 676 piece_set(&simulation, row, file, mkpiece(PAWN, opcolor)); |
674 piece_set(&simulation, row, file, mkpiece(PAWN, opcolor)); |
| 742 gamestate_cleanup(&simulation); |
740 gamestate_cleanup(&simulation); |
| 743 |
741 |
| 744 return covered; |
742 return covered; |
| 745 } |
743 } |
| 746 |
744 |
| |
745 bool get_real_candidates(const GameState *gamestate, Row row, File file, |
| |
746 Color color, Move *moves, size_t *movecount) { |
| |
747 |
| |
748 if (movecount) { |
| |
749 *movecount = 0; |
| |
750 } |
| |
751 |
| |
752 Move candidates[16]; |
| |
753 size_t ccount; |
| |
754 if (get_candidates(gamestate, row, file, color, candidates, &ccount)) { |
| |
755 bool result = false; |
| |
756 for (size_t i = 0 ; i < ccount ; i++) { |
| |
757 if (!is_pinned(gamestate, &candidates[i])) { |
| |
758 result = true; |
| |
759 if (moves && movecount) { |
| |
760 moves[(*movecount)++] = candidates[i]; |
| |
761 } |
| |
762 } |
| |
763 } |
| |
764 return result; |
| |
765 } else { |
| |
766 return false; |
| |
767 } |
| |
768 } |
| |
769 |
| 747 bool get_real_threats(const GameState *gamestate, Row row, File file, |
770 bool get_real_threats(const GameState *gamestate, Row row, File file, |
| 748 Color color, Move *threats, size_t *threatcount) { |
771 Color color, Move *threats, size_t *threatcount) { |
| 749 |
772 |
| 750 if (threatcount) { |
773 if (threatcount) { |
| 751 *threatcount = 0; |
774 *threatcount = 0; |
| 752 } |
775 } |
| 753 |
776 |
| 754 Move candidates[16]; |
777 Move candidates[16]; |
| 755 size_t candidatecount; |
778 size_t ccount; |
| 756 if (get_threats(gamestate, row, file, color, candidates, &candidatecount)) { |
779 if (get_threats(gamestate, row, file, color, candidates, &ccount)) { |
| 757 |
|
| 758 bool result = false; |
780 bool result = false; |
| 759 File kingfile = 0; |
781 for (size_t i = 0 ; i < ccount ; i++) { |
| 760 Row kingrow = 0; |
782 if (!is_pinned(gamestate, &candidates[i])) { |
| 761 for (Row r = 0 ; r < 8 ; r++) { |
|
| 762 for (File f = 0 ; f < 8 ; f++) { |
|
| 763 if (gamestate->board[r][f] == (color|KING)) { |
|
| 764 kingfile = f; |
|
| 765 kingrow = r; |
|
| 766 } |
|
| 767 } |
|
| 768 } |
|
| 769 |
|
| 770 for (size_t i = 0 ; i < candidatecount ; i++) { |
|
| 771 // TODO: check if we really need full-blown simulations here |
|
| 772 GameState simulation = gamestate_copy_sim(gamestate); |
|
| 773 Move simmove = candidates[i]; |
|
| 774 apply_move(&simulation, &simmove); |
|
| 775 if (!is_covered(&simulation, kingrow, kingfile, |
|
| 776 opponent_color(color))) { |
|
| 777 result = true; |
783 result = true; |
| 778 if (threats && threatcount) { |
784 if (threats && threatcount) { |
| 779 threats[(*threatcount)++] = candidates[i]; |
785 threats[(*threatcount)++] = candidates[i]; |
| 780 } |
786 } |
| 781 } |
787 } |
| 782 gamestate_cleanup(&simulation); |
788 } |
| 783 } |
|
| 784 |
|
| 785 return result; |
789 return result; |
| 786 } else { |
790 } else { |
| 787 return false; |
791 return false; |
| 788 } |
792 } |
| 789 } |
793 } |