Парсер FEN на Си
Feb. 13th, 2012 10:07 pmА не распарсить ли мне FEN на Сях, раз такая пьянка? Распаршу:
#include <assert.h> #include <ctype.h> #include <stdio.h> #define RANK "%8[12345678PNBRQKpnbrqk]" #define ENPASS "%2[abcdefgh12345678-]" #define FEN \ RANK "/" RANK "/" RANK "/" RANK "/" \ RANK "/" RANK "/" RANK "/" RANK " " \ "%1[wb] %4[KQkq-] " ENPASS " %*2d %*d\n" #define RANKS(board) \ (board)[7], (board)[6], (board)[5], (board)[4], \ (board)[3], (board)[2], (board)[1], (board)[0]
static fen()
{
struct {
char board[8][9];
int enpassi, enpassj;
enum {
WHITE, BLACK
} act;
struct {
int cshort, clong;
} white, black;
} pos;
char buf[8][9], act[2], cast[5], enpass[3];
int n, i, j;
n = scanf(FEN, RANKS(buf), act, cast, enpass);
assert(11 == n);
pos.act = ('w' == act[0]) ? WHITE : BLACK;
pos.enpassi = enpass[1] - '1';
pos.enpassj = enpass[0] - 'a';
pos.white.cshort = ('K' == cast[0]);
pos.white.clong = ('Q' == cast[1]);
pos.black.cshort = ('k' == cast[2]);
pos.black.clong = ('q' == cast[3]);
for (i = 0; i < 8; i++) {
const char *src = buf[i];
char *dst = pos.board[i];
int sq = 0;
for (j = 0; j < 8; j++) {
char piece = src[j];
if (!piece) {
assert(8 == sq);
break;
} else if (isdigit(piece)) {
int skip = piece - '0';
while (skip) {
assert(sq < 8);
dst[sq] = '.';
++sq;
--skip;
}
} else {
assert(sq < 8);
dst[sq] = src[j];
++sq;
}
}
}
for (i = 7; i > -1; i--)
printf("%.8s\n", pos.board[i]);
printf("%s's move\n", pos.act ? "Black" : "White");
return 0;
}
main()
{
while (!feof(stdin))
fen();
return 0;
}