src/chess/pgn.c

changeset 54
eef745ba3774
parent 50
41017d0a72c5
child 55
54ea19938d57
equal deleted inserted replaced
53:78b580bfde33 54:eef745ba3774
192 } 192 }
193 193
194 194
195 return bytes; 195 return bytes;
196 } 196 }
197
198 static size_t fen_pieces(char *str, GameState *gamestate) {
199 size_t i = 0;
200 for (int row = 7 ; row >= 0 ; row--) {
201 unsigned int skip = 0;
202 for (int file = 0 ; file < 8 ; file++) {
203 if (gamestate->board[row][file]) {
204 if (skip > 0) {
205 str[i++] = '0'+skip;
206 skip = 0;
207 }
208 switch (gamestate->board[row][file] & ~ENPASSANT_THREAT) {
209 case WHITE|KING: str[i++] = 'K'; break;
210 case WHITE|QUEEN: str[i++] = 'Q'; break;
211 case WHITE|BISHOP: str[i++] = 'B'; break;
212 case WHITE|KNIGHT: str[i++] = 'N'; break;
213 case WHITE|ROOK: str[i++] = 'R'; break;
214 case WHITE|PAWN: str[i++] = 'P'; break;
215 case BLACK|KING: str[i++] = 'k'; break;
216 case BLACK|QUEEN: str[i++] = 'q'; break;
217 case BLACK|BISHOP: str[i++] = 'b'; break;
218 case BLACK|KNIGHT: str[i++] = 'n'; break;
219 case BLACK|ROOK: str[i++] = 'r'; break;
220 case BLACK|PAWN: str[i++] = 'p'; break;
221 }
222 } else {
223 skip++;
224 }
225 }
226 if (skip > 0) {
227 str[i++] = '0'+skip;
228 }
229 if (row > 0) {
230 str[i++] = '/';
231 }
232 }
233
234 return i;
235 }
236
237 static size_t fen_color(char *str, GameState *gamestate) {
238 uint8_t color = opponent_color(gamestate->lastmove ?
239 (gamestate->lastmove->move.piece & COLOR_MASK) : BLACK);
240
241 str[0] = color == WHITE ? 'w' : 'b';
242
243 return 1;
244 }
245
246 static _Bool fen_castling_chkmoved(GameState *gamestate,
247 uint8_t row, uint8_t file) {
248
249 MoveList *ml = gamestate->movelist;
250 while (ml) {
251 if (ml->move.fromfile == file && ml->move.fromrow == row) {
252 return 1;
253 }
254 ml = ml->next;
255 }
256
257 return 0;
258 }
259
260 static size_t fen_castling(char *str, GameState *gamestate) {
261 _Bool K, Q, k, q;
262
263 if (fen_castling_chkmoved(gamestate, rowidx('1'), fileidx('e'))) {
264 K = Q = 0;
265 } else {
266 K = !fen_castling_chkmoved(gamestate, rowidx('1'), fileidx('h'));
267 Q = !fen_castling_chkmoved(gamestate, rowidx('1'), fileidx('a'));
268 }
269 if (fen_castling_chkmoved(gamestate, rowidx('8'), fileidx('e'))) {
270 k = q = 0;
271 } else {
272 k = !fen_castling_chkmoved(gamestate, rowidx('8'), fileidx('h'));
273 q = !fen_castling_chkmoved(gamestate, rowidx('8'), fileidx('a'));
274 }
275
276 size_t i = 0;
277 if (K) str[i++] = 'K';
278 if (Q) str[i++] = 'Q';
279 if (k) str[i++] = 'k';
280 if (q) str[i++] = 'q';
281 if (!i) str[i++] = '-';
282
283 return i;
284 }
285
286 static size_t fen_enpassant(char *str, GameState *gamestate) {
287
288 str[0] = '-'; str[1] = '\0';
289
290 for (int file = 0 ; file < 8 ; file++) {
291 if (gamestate->board[3][file] & ENPASSANT_THREAT) {
292 str[0] = filechr(file);
293 str[1] = rowchr(2);
294 }
295 if (gamestate->board[4][file] & ENPASSANT_THREAT) {
296 str[0] = filechr(file);
297 str[1] = rowchr(5);
298 }
299 }
300
301 return str[0] == '-' ? 1 : 2;
302 }
303
304 static size_t fen_halfmove(char *str, GameState *gamestate) {
305
306 unsigned int i = 0;
307 for (MoveList *move = gamestate->movelist ; move ; move = move->next) {
308 if (move->move.capture || (move->move.piece & PIECE_MASK) == PAWN) {
309 i = 0;
310 } else {
311 i++;
312 }
313 }
314
315 char m[8];
316 size_t len = sprintf(m, "%u", i);
317 memcpy(str, m, len);
318
319 return len;
320 }
321
322 static size_t fen_movenr(char *str, GameState *gamestate) {
323
324 MoveList *move = gamestate->movelist;
325 unsigned int i = 1;
326 while (move) {
327 i++;
328 move = move->next;
329 }
330
331 char m[8];
332 size_t len = sprintf(m, "%u", i);
333 memcpy(str, m, len);
334
335 return len;
336 }
337
338 void compute_fen(char *str, GameState *gamestate) {
339 str += fen_pieces(str, gamestate);
340 *str = ' '; str++;
341 str += fen_color(str, gamestate);
342 *str = ' '; str++;
343 str += fen_castling(str, gamestate);
344 *str = ' '; str++;
345 str += fen_enpassant(str, gamestate);
346 *str = ' '; str++;
347 str += fen_halfmove(str, gamestate);
348 *str = ' '; str++;
349 str += fen_movenr(str, gamestate);
350 str[0] = '\0';
351 }

mercurial