| 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( |
33 static bool king_castling_chkmoved( |
| 34 const GameState *gamestate, Row row, File file) { |
34 const GameState *gamestate, Rank rank, File file) { |
| 35 |
35 |
| 36 for (unsigned i = 0; i < gamestate->movecount; i++) { |
36 for (unsigned i = 0; i < gamestate->movecount; i++) { |
| 37 if (gamestate->moves[i].fromfile == file |
37 if (gamestate->moves[i].fromfile == file |
| 38 && gamestate->moves[i].fromrow == row) { |
38 && gamestate->moves[i].fromrank == rank) { |
| 39 return true; |
39 return true; |
| 40 } |
40 } |
| 41 } |
41 } |
| 42 |
42 |
| 43 return false; |
43 return false; |
| 44 } |
44 } |
| 45 |
45 |
| 46 bool king_chkrules(const GameState *gamestate, const Move* move) { |
46 bool king_chkrules(const GameState *gamestate, const Move* move) { |
| 47 if (abs(move->torow - move->fromrow) <= 1 && |
47 if (abs(move->torank - move->fromrank) <= 1 && |
| 48 abs(move->tofile - move->fromfile) <= 1) { |
48 abs(move->tofile - move->fromfile) <= 1) { |
| 49 return true; |
49 return true; |
| 50 } else { |
50 } else { |
| 51 /* castling */ |
51 /* castling */ |
| 52 if (move->fromrow == move->torow && |
52 if (move->fromrank == move->torank && |
| 53 move->fromrow == (piece_color(move->piece) == WHITE ? 0 : 7) && |
53 move->fromrank == (piece_color(move->piece) == WHITE ? 0 : 7) && |
| 54 move->fromfile == fileidx('e') && |
54 move->fromfile == fileidx('e') && |
| 55 (move->tofile == fileidx('c') || move->tofile == fileidx('g'))) { |
55 (move->tofile == fileidx('c') || move->tofile == fileidx('g'))) { |
| 56 |
56 |
| 57 return !king_castling_chkmoved(gamestate, |
57 return !king_castling_chkmoved(gamestate, |
| 58 move->fromrow, move->fromfile) && |
58 move->fromrank, move->fromfile) && |
| 59 !king_castling_chkmoved(gamestate, move->fromrow, |
59 !king_castling_chkmoved(gamestate, move->fromrank, |
| 60 move->tofile == fileidx('c') ? 0 : 7); |
60 move->tofile == fileidx('c') ? 0 : 7); |
| 61 } else { |
61 } else { |
| 62 return false; |
62 return false; |
| 63 } |
63 } |
| 64 } |
64 } |
| 65 } |
65 } |
| 66 |
66 |
| 67 bool king_isblocked(const GameState *gamestate, const Move *move) { |
67 bool king_isblocked(const GameState *gamestate, const Move *move) { |
| 68 |
68 |
| 69 uint8_t op_color = opponent_color(piece_color(move->piece)); |
69 Color op_color = opponent_color(piece_color(move->piece)); |
| 70 |
70 |
| 71 /* being in check does not "block" the king, so don't test it here */ |
71 /* being in check does not "block" the king, so don't test it here */ |
| 72 bool blocked = false; |
72 bool blocked = false; |
| 73 |
73 |
| 74 /* just test, if castling move is blocked */ |
74 /* just test, if castling move is blocked */ |
| 75 if (abs(move->tofile - move->fromfile) == 2) { |
75 if (abs(move->tofile - move->fromfile) == 2) { |
| 76 if (move->tofile == fileidx('c')) { |
76 if (move->tofile == fileidx('c')) { |
| 77 blocked |= gamestate->board[move->torow][fileidx('b')]; |
77 blocked |= gamestate->board[move->torank][fileidx('b')]; |
| 78 } |
78 } |
| 79 uint8_t midfile = (move->tofile+move->fromfile)/2; |
79 File midfile = (move->tofile+move->fromfile)/2; |
| 80 bool incheck = false; |
80 bool incheck = false; |
| 81 if (gamestate->movecount > 0) { |
81 if (gamestate->movecount > 0) { |
| 82 incheck = is_check_position(gamestate); |
82 incheck = is_check_position(gamestate); |
| 83 } |
83 } |
| 84 blocked |= incheck || gamestate->board[move->torow][midfile] || |
84 blocked |= incheck || gamestate->board[move->torank][midfile] || |
| 85 is_covered(gamestate, move->torow, midfile, op_color); |
85 is_covered(gamestate, move->torank, midfile, op_color); |
| 86 } |
86 } |
| 87 |
87 |
| 88 return blocked; |
88 return blocked; |
| 89 } |
89 } |
| 90 |
90 |
| 91 size_t king_moves(const GameState *gamestate, |
91 size_t king_moves(const GameState *gamestate, |
| 92 Color c, Row r, File f, Move *moves) { |
92 Color c, Rank r, File f, Move *moves) { |
| 93 |
93 |
| 94 size_t count = 0; |
94 size_t count = 0; |
| 95 Piece king = mkpiece(KING, c); |
95 Piece king = mkpiece(KING, c); |
| 96 |
96 |
| 97 for (int dr = -1 ; dr <= 1 ; dr++) { |
97 for (int dr = -1 ; dr <= 1 ; dr++) { |
| 98 for (int df = -1 ; df <= 1 ; df++) { |
98 for (int df = -1 ; df <= 1 ; df++) { |
| 99 if (dr == 0 && df == 0) { |
99 if (dr == 0 && df == 0) { |
| 100 continue; |
100 continue; |
| 101 } |
101 } |
| 102 |
102 |
| 103 Row torow = r + dr; |
103 Rank torank = r + dr; |
| 104 File tofile = f + df; |
104 File tofile = f + df; |
| 105 |
105 |
| 106 if (!isidx(torow) || !isidx(tofile)) { |
106 if (!isidx(torank) || !isidx(tofile)) { |
| 107 continue; |
107 continue; |
| 108 } |
108 } |
| 109 |
109 |
| 110 moves[count] = (Move){0}; |
110 moves[count] = (Move){0}; |
| 111 moves[count].piece = king; |
111 moves[count].piece = king; |
| 112 moves[count].fromrow = r; |
112 moves[count].fromrank = r; |
| 113 moves[count].fromfile = f; |
113 moves[count].fromfile = f; |
| 114 moves[count].torow = torow; |
114 moves[count].torank = torank; |
| 115 moves[count].tofile = tofile; |
115 moves[count].tofile = tofile; |
| 116 moves[count].capture = piece_at(gamestate, torow, tofile) != 0; |
116 moves[count].capture = piece_at(gamestate, torank, tofile) != 0; |
| 117 count++; |
117 count++; |
| 118 } |
118 } |
| 119 } |
119 } |
| 120 |
120 |
| 121 Row homerow = c == WHITE ? 0 : 7; |
121 Rank homerank = c == WHITE ? 0 : 7; |
| 122 if (r == homerow && f == fileidx('e')) { |
122 if (r == homerank && f == fileidx('e')) { |
| 123 moves[count] = (Move){0}; |
123 moves[count] = (Move){0}; |
| 124 moves[count].piece = king; |
124 moves[count].piece = king; |
| 125 moves[count].fromrow = r; |
125 moves[count].fromrank = r; |
| 126 moves[count].fromfile = f; |
126 moves[count].fromfile = f; |
| 127 moves[count].torow = r; |
127 moves[count].torank = r; |
| 128 moves[count].tofile = fileidx('c'); |
128 moves[count].tofile = fileidx('c'); |
| 129 count++; |
129 count++; |
| 130 |
130 |
| 131 moves[count] = (Move){0}; |
131 moves[count] = (Move){0}; |
| 132 moves[count].piece = king; |
132 moves[count].piece = king; |
| 133 moves[count].fromrow = r; |
133 moves[count].fromrank = r; |
| 134 moves[count].fromfile = f; |
134 moves[count].fromfile = f; |
| 135 moves[count].torow = r; |
135 moves[count].torank = r; |
| 136 moves[count].tofile = fileidx('g'); |
136 moves[count].tofile = fileidx('g'); |
| 137 count++; |
137 count++; |
| 138 } |
138 } |
| 139 |
139 |
| 140 return count; |
140 return count; |