| 28 */ |
28 */ |
| 29 |
29 |
| 30 #include "rules.h" |
30 #include "rules.h" |
| 31 #include "king.h" |
31 #include "king.h" |
| 32 |
32 |
| 33 static bool king_castling_chkmoved( |
|
| 34 const GameState *gamestate, File file, Rank rank) { |
|
| 35 |
|
| 36 for (unsigned i = 0; i < gamestate->movecount; i++) { |
|
| 37 if (gamestate->moves[i].fromfile == file |
|
| 38 && gamestate->moves[i].fromrank == rank) { |
|
| 39 return true; |
|
| 40 } |
|
| 41 } |
|
| 42 |
|
| 43 return false; |
|
| 44 } |
|
| 45 |
|
| 46 bool king_chkrules(const GameState *gamestate, const Move* move) { |
33 bool king_chkrules(const GameState *gamestate, const Move* move) { |
| 47 if (abs(move->torank - move->fromrank) <= 1 && |
34 if (abs(move->torank - move->fromrank) <= 1 && |
| 48 abs(move->tofile - move->fromfile) <= 1) { |
35 abs(move->tofile - move->fromfile) <= 1) { |
| 49 return true; |
36 return true; |
| |
37 } else if (move->fromrank == move->torank) { |
| |
38 /* castling */ |
| |
39 Rank backrank; |
| |
40 bool k_allowed, q_allowed; |
| |
41 if (piece_color(move->piece) == WHITE) { |
| |
42 backrank = rankidx('1'); |
| |
43 k_allowed = !gamestate->castling.K; |
| |
44 q_allowed = !gamestate->castling.Q; |
| |
45 } else { |
| |
46 backrank = rankidx('8'); |
| |
47 k_allowed = !gamestate->castling.k; |
| |
48 q_allowed = !gamestate->castling.q; |
| |
49 } |
| |
50 bool castle_q = false, castle_k = false; |
| |
51 if (move->fromrank == backrank && move->fromfile == fileidx('e')) { |
| |
52 castle_q = move->tofile == fileidx('c'); |
| |
53 castle_k = move->tofile == fileidx('g'); |
| |
54 } |
| |
55 /* note that here we do not consider threats! |
| |
56 * that is what king_isblocked() does */ |
| |
57 return (castle_q && q_allowed) || (castle_k && k_allowed); |
| 50 } else { |
58 } else { |
| 51 /* castling */ |
59 return false; |
| 52 if (move->fromrank == move->torank && |
|
| 53 move->fromrank == (piece_color(move->piece) == WHITE ? 0 : 7) && |
|
| 54 move->fromfile == fileidx('e') && |
|
| 55 (move->tofile == fileidx('c') || move->tofile == fileidx('g'))) { |
|
| 56 |
|
| 57 return !king_castling_chkmoved(gamestate, |
|
| 58 move->fromfile, move->fromrank) && |
|
| 59 !king_castling_chkmoved(gamestate, |
|
| 60 move->tofile == fileidx('c') ? 0 : 7, move->fromrank); |
|
| 61 } else { |
|
| 62 return false; |
|
| 63 } |
|
| 64 } |
60 } |
| 65 } |
61 } |
| 66 |
62 |
| 67 bool king_isblocked(const GameState *gamestate, const Move *move) { |
63 bool king_isblocked(const GameState *gamestate, const Move *move) { |
| 68 |
|
| 69 Color op_color = opponent_color(piece_color(move->piece)); |
|
| 70 |
|
| 71 /* being in check does not "block" the king, so don't test it here */ |
|
| 72 bool blocked = false; |
|
| 73 |
|
| 74 /* just test, if castling move is blocked */ |
64 /* just test, if castling move is blocked */ |
| 75 if (abs(move->tofile - move->fromfile) == 2) { |
65 if (abs(move->tofile - move->fromfile) == 2) { |
| 76 if (move->tofile == fileidx('c')) { |
66 if (move->tofile == fileidx('c')) { |
| 77 blocked |= gamestate->board[move->torank][fileidx('b')]; |
67 /* check if rook can travel the queen-side */ |
| |
68 if (gamestate->board[move->torank][fileidx('b')]) { |
| |
69 return true; |
| |
70 } |
| 78 } |
71 } |
| |
72 /* check if new field for the rook is free */ |
| 79 File midfile = (move->tofile+move->fromfile)/2; |
73 File midfile = (move->tofile+move->fromfile)/2; |
| 80 bool incheck = false; |
74 if (gamestate->board[move->torank][midfile]) { |
| 81 if (gamestate->movecount > 0) { |
75 return true; |
| 82 incheck = is_check_position(gamestate); |
|
| 83 } |
76 } |
| 84 blocked |= incheck || gamestate->board[move->torank][midfile] || |
77 /* check if the king or the target field for the rook is threatened */ |
| 85 is_covered(gamestate, midfile, move->torank, op_color); |
78 if (is_check_position(gamestate) || is_covered(gamestate, |
| |
79 midfile, move->torank, opponent_color(piece_color(move->piece)))) { |
| |
80 return true; |
| |
81 } |
| 86 } |
82 } |
| 87 |
83 return false; |
| 88 return blocked; |
|
| 89 } |
84 } |
| 90 |
85 |
| 91 size_t king_moves(const GameState *gamestate, |
86 size_t king_moves(const GameState *gamestate, |
| 92 Color c, File f, Rank r, Move *moves) { |
87 Color c, File f, Rank r, Move *moves) { |
| 93 |
88 |