| 133 // TODO: make it so |
133 // TODO: make it so |
| 134 |
134 |
| 135 return result; |
135 return result; |
| 136 } |
136 } |
| 137 |
137 |
| |
138 /** |
| |
139 * Maps a character to a piece. |
| |
140 * |
| |
141 * Does not work for pawns, since they don't have a character. |
| |
142 * |
| |
143 * @param c one of R,N,B,Q,K |
| |
144 * @return numeric value for the specified piece |
| |
145 */ |
| |
146 static uint8_t getpiece(char c) { |
| |
147 switch (c) { |
| |
148 case 'R': return ROOK; |
| |
149 case 'N': return KNIGHT; |
| |
150 case 'B': return BISHOP; |
| |
151 case 'Q': return QUEEN; |
| |
152 case 'K': return KING; |
| |
153 default: return 0; |
| |
154 } |
| |
155 } |
| |
156 |
| |
157 /** |
| |
158 * Guesses the location of a piece for short algebraic notation. |
| |
159 * |
| |
160 * @param board the current state of the board |
| |
161 * @param move the move date to operate on |
| |
162 * @return TRUE if the location could be retrieved, FALSE if the location is |
| |
163 * ambiguous |
| |
164 */ |
| |
165 static _Bool getlocation(Board board, Move *move) { |
| |
166 uint8_t piece = move->piece & PIECE_MASK; |
| |
167 switch (piece) { |
| |
168 case PAWN: return pawn_getlocation(board, move); |
| |
169 case ROOK: return rook_getlocation(board, move); |
| |
170 case KNIGHT: return knight_getlocation(board, move); |
| |
171 case BISHOP: return bishop_getlocation(board, move); |
| |
172 case QUEEN: return queen_getlocation(board, move); |
| |
173 case KING: return king_getlocation(board, move); |
| |
174 default: return FALSE; |
| |
175 } |
| |
176 } |
| |
177 |
| |
178 /** |
| |
179 * Evaluates a move syntactically and stores the move data in the specified |
| |
180 * object. |
| |
181 * |
| |
182 * @param board the current state of the board |
| |
183 * @param mycolor the color of the current player |
| |
184 * @param mstr the input string to parse |
| |
185 * @param move a pointer to object where the move data shall be stored |
| |
186 * @return TRUE, if the move is syntactically valid, FALSE otherwise |
| |
187 */ |
| 138 static _Bool eval_move(Board board, uint8_t mycolor, char *mstr, Move *move) { |
188 static _Bool eval_move(Board board, uint8_t mycolor, char *mstr, Move *move) { |
| 139 memset(move, 0, sizeof(Move)); |
189 memset(move, 0, sizeof(Move)); |
| |
190 move->fromfile = POS_UNSPECIFIED; |
| |
191 move->fromrow = POS_UNSPECIFIED; |
| 140 |
192 |
| 141 size_t len = strlen(mstr); |
193 size_t len = strlen(mstr); |
| 142 |
194 |
| 143 /* evaluate check/checkmate flags */ |
195 /* evaluate check/checkmate flags */ |
| 144 if (mstr[len-1] == '+') { |
196 if (mstr[len-1] == '+') { |
| 150 } |
202 } |
| 151 |
203 |
| 152 if (len == 2) { |
204 if (len == 2) { |
| 153 /* pawn move (e.g. "e4") */ |
205 /* pawn move (e.g. "e4") */ |
| 154 if (isfile(mstr[0]) && isrow(mstr[1])) { |
206 if (isfile(mstr[0]) && isrow(mstr[1])) { |
| 155 move->piece = PAWN|mycolor; |
207 move->piece = PAWN; |
| 156 move->tofile = fileidx(mstr[0]); |
208 move->tofile = fileidx(mstr[0]); |
| 157 move->torow = rowidx(mstr[1]); |
209 move->torow = rowidx(mstr[1]); |
| 158 if (!pawn_getlocation(board, move)) { |
|
| 159 move->piece = 0; |
|
| 160 } |
|
| 161 } |
210 } |
| 162 } else if (len == 3) { |
211 } else if (len == 3) { |
| 163 if (strcmp(mstr, "O-O") == 0) { |
212 if (strcmp(mstr, "O-O") == 0) { |
| 164 /* king side castling */ |
213 /* king side castling */ |
| 165 move->piece = KING|mycolor; |
214 move->piece = KING; |
| 166 move->fromfile = fileidx('e'); |
215 move->fromfile = fileidx('e'); |
| 167 move->tofile = fileidx('g'); |
216 move->tofile = fileidx('g'); |
| 168 move->fromrow = move->torow = mycolor == WHITE ? 0 : 7; |
217 move->fromrow = move->torow = mycolor == WHITE ? 0 : 7; |
| 169 } else { |
218 } else { |
| 170 /* unambiguous move (e.g. "Nf3") */ |
219 /* unambiguous move (e.g. "Nf3") */ |
| |
220 move->piece = getpiece(mstr[0]); |
| |
221 move->tofile = isfile(mstr[1]) ? fileidx(mstr[1]) : POS_UNSPECIFIED; |
| |
222 move->torow = isrow(mstr[2]) ? fileidx(mstr[2]) : POS_UNSPECIFIED; |
| 171 } |
223 } |
| 172 |
224 |
| 173 } else if (len == 4) { |
225 } else if (len == 4) { |
| 174 /* ambiguous move (e.g. "Ndf3") */ |
226 /* ambiguous move (e.g. "Ndf3") */ |
| 175 |
227 |
| 176 /* unambiguous capture (e.g. "Nxf3", "dxe5") */ |
228 /* unambiguous capture (e.g. "Nxf3", "dxe5") */ |
| 177 |
229 |
| 178 } else if (len == 5) { |
230 } else if (len == 5) { |
| 179 if (strcmp(mstr, "O-O-O") == 0) { |
231 if (strcmp(mstr, "O-O-O") == 0) { |
| 180 /* queen side castling "O-O-O" */ |
232 /* queen side castling "O-O-O" */ |
| 181 move->piece = KING|mycolor; |
233 move->piece = KING; |
| 182 move->fromfile = fileidx('e'); |
234 move->fromfile = fileidx('e'); |
| 183 move->tofile = fileidx('c'); |
235 move->tofile = fileidx('c'); |
| 184 move->fromrow = move->torow = mycolor == WHITE ? 0 : 7; |
236 move->fromrow = move->torow = mycolor == WHITE ? 0 : 7; |
| 185 } else { |
237 } else { |
| 186 /* ambiguous capture (e.g. "Ndxf3") */ |
238 /* ambiguous capture (e.g. "Ndxf3") */ |
| 189 |
241 |
| 190 /* long notation capture (e.g. "e5xf6") */ |
242 /* long notation capture (e.g. "e5xf6") */ |
| 191 } |
243 } |
| 192 } else if (len == 6) { |
244 } else if (len == 6) { |
| 193 /* long notation capture (e.g. "Nc5xf3") */ |
245 /* long notation capture (e.g. "Nc5xf3") */ |
| |
246 } |
| |
247 |
| |
248 if (move->piece) { |
| |
249 move->piece |= mycolor; |
| |
250 } |
| |
251 |
| |
252 if (!getlocation(board, move)) { |
| |
253 // TODO: return status code to indicate the error type |
| |
254 move->piece = 0; |
| 194 } |
255 } |
| 195 |
256 |
| 196 return move->piece != 0; |
257 return move->piece != 0; |
| 197 } |
258 } |
| 198 |
259 |