improve and extend FEN parsing and FEN output - chess-puzzles - chess puzzle bo… | |
git clone git://git.codemadness.org/chess-puzzles | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 132c4a50aae9c410bf3b505f4c61b322c388cf83 | |
parent 29822d687c7eed634e2fd6b480ddbf84cbabf4c2 | |
Author: Hiltjo Posthuma <[email protected]> | |
Date: Tue, 19 Dec 2023 20:11:09 +0100 | |
improve and extend FEN parsing and FEN output | |
- improve castling availability: no castle detection yet. | |
- initial halfmove and move number parsing. | |
- parse enpassant move, but no enpassant detection yet. | |
- increase move number by a move by black. | |
work in progress | |
Diffstat: | |
M fen_to_svg.c | 116 ++++++++++++++++++++++-------… | |
1 file changed, 85 insertions(+), 31 deletions(-) | |
--- | |
diff --git a/fen_to_svg.c b/fen_to_svg.c | |
@@ -2,6 +2,7 @@ | |
#include <ctype.h> | |
#include <stdio.h> | |
+#include <stdlib.h> | |
#include <string.h> | |
#define SETFGCOLOR(r,g,b) printf("\x1b[38;2;%d;%d;%dm", r, g, b) | |
@@ -11,8 +12,11 @@ static char board[8][8]; | |
static char highlight[8][8]; | |
static int side_to_move = 'w'; /* default: white to move */ | |
-static int white_can_castle[2] = { 0, 0 }; /* allow king side, allow queen sid… | |
-static int black_can_castle[2] = { 0, 0 }; /* allow king side, allow queen sid… | |
+static int white_can_castle[2] = { 0, 0 }; /* allow king side, allow queen sid… | |
+static int black_can_castle[2] = { 0, 0 }; /* allow king side, allow queen sid… | |
+static int enpassantsquare[2] = { -1, -1 }; | |
+static int movenumber = 1; | |
+static int halfmove = 0; | |
static const int showcoords = 1; /* config: show board coordinates? */ | |
@@ -94,6 +98,27 @@ showboardfen(void) | |
if (skip) | |
putchar(skip + '0'); | |
} | |
+ printf(" %c ", side_to_move); | |
+ if (white_can_castle[0]) | |
+ putchar('K'); | |
+ if (white_can_castle[1]) | |
+ putchar('Q'); | |
+ if (black_can_castle[0]) | |
+ putchar('k'); | |
+ if (black_can_castle[1]) | |
+ putchar('q'); | |
+ if ((white_can_castle[0] + white_can_castle[1] + | |
+ black_can_castle[0] + black_can_castle[1]) == 0) | |
+ putchar('-'); /* no castling for either side */ | |
+ putchar(' '); | |
+ | |
+ if (enpassantsquare[0] != -1 && enpassantsquare[1] != -1) { | |
+ putchar('a' + enpassantsquare[0]); | |
+ putchar('8' - enpassantsquare[1]); | |
+ } else { | |
+ putchar('-'); | |
+ } | |
+ printf(" %d %d", halfmove, movenumber); | |
/* ? TODO: detect en passant, invalid castling etc? */ | |
} | |
@@ -333,7 +358,7 @@ ascii_showboard(void) | |
printf("\n\n"); | |
for (y = 0; y < 8; y++) { | |
- printf("+---+---+---+---+---+---+---+---+\n"); | |
+ fputs("+---+---+---+---+---+---+---+---+\n", stdout); | |
for (x = 0; x < 8; x++) { | |
if (x == 0) | |
putchar('|'); | |
@@ -343,8 +368,7 @@ ascii_showboard(void) | |
ascii_showpiece(piece); | |
else | |
fputs(" ", stdout); | |
- fputs(" ", stdout); | |
- putchar('|'); | |
+ fputs(" |", stdout); | |
} | |
if (showcoords) { | |
putchar(' '); | |
@@ -352,35 +376,20 @@ ascii_showboard(void) | |
} | |
putchar('\n'); | |
} | |
- printf("+---+---+---+---+---+---+---+---+\n"); | |
+ fputs("+---+---+---+---+---+---+---+---+\n", stdout); | |
if (showcoords) | |
printf(" a | b | c | d | e | f | g | h |\n"); | |
fputs("\n", stdout); | |
- | |
-#if 0 | |
- if (side_to_move == 'w') { | |
- fputs("White to move\n", stdout); | |
- } else if (side_to_move == 'b') | |
- fputs("Black to move\n", stdout); | |
- | |
- if (white_can_castle[0]) | |
- fputs("White can castle king side\n", stdout); | |
- if (white_can_castle[1]) | |
- fputs("White can castle queen side\n", stdout); | |
- if (black_can_castle[0]) | |
- fputs("Black can castle king side\n", stdout); | |
- if (black_can_castle[1]) | |
- fputs("Black can castle queen side\n", stdout); | |
-#endif | |
} | |
int | |
main(int argc, char *argv[]) | |
{ | |
const char *progname, *fen, *moves, *s; | |
- int x, y, x2, y2, field, piece; | |
+ int x, y, x2, y2, field, piece, takepiece; | |
char square[3]; | |
+ long l; | |
if (argc != 3) { | |
fprintf(stderr, "usage: %s <FEN> <moves>\n", argv[0]); | |
@@ -396,14 +405,6 @@ main(int argc, char *argv[]) | |
/* initial board state, FEN format */ | |
x = y = field = 0; | |
for (s = fen; *s; s++) { | |
- /* next field, fields are: piece placement data, active color, | |
- Castling availability, En passant target square, | |
- Halfmove clock, Fullmove number */ | |
- if (*s == ' ') { | |
- field++; | |
- continue; | |
- } | |
- | |
switch (field) { | |
case 0: /* piece placement data */ | |
/* skip square */ | |
@@ -442,9 +443,48 @@ main(int argc, char *argv[]) | |
} | |
break; | |
case 3: /* TODO: en-passant square, rest of the fields */ | |
+ if (*s >= 'a' && *s <= 'h' && | |
+ *(s + 1) >= '1' && *(s + 1) >= '6') { | |
+ | |
+ square[0] = *s; | |
+ square[1] = *(s + 1); | |
+ square[2] = '\0'; | |
+ squaretoxy(square, &x, &y); | |
+ | |
+ enpassantsquare[0] = x; | |
+ enpassantsquare[1] = y; | |
+ } | |
+ break; | |
+ case 4: /* halfmove */ | |
+ if (!(*s >= '0' && *s <= '9')) | |
+ continue; | |
+ | |
+ l = strtol(s, NULL, 10); | |
+ if (l >= 0 && l < 32767) { | |
+ halfmove = l; | |
+ s += strspn(s, "0123456789"); | |
+ } | |
+ break; | |
+ case 5: /* move number */ | |
+ if (!(*s >= '0' && *s <= '9')) | |
+ continue; | |
+ | |
+ l = strtol(s, NULL, 10); | |
+ if (l >= 0 && l < 32767) { | |
+ movenumber = l; | |
+ s += strspn(s, "0123456789"); | |
+ } | |
break; | |
} | |
/* TODO: parse which side to move, en-passant, etc */ | |
+ | |
+ /* next field, fields are: piece placement data, active color, | |
+ Castling availability, En passant target square, | |
+ Halfmove clock, Fullmove number */ | |
+ if (*s == ' ') { | |
+ field++; | |
+ continue; | |
+ } | |
} | |
/* process moves */ | |
@@ -470,9 +510,17 @@ main(int argc, char *argv[]) | |
square[0] = *s; | |
square[1] = *(s + 1); | |
squaretoxy(square, &x2, &y2); | |
+ takepiece = getpiece(x, y); | |
place(piece, x2, y2); | |
s += 2; | |
+ /* if pawn move or taken a piece increase halfmove cou… | |
+ /* TODO: taking enpassant should reset halfmove too */ | |
+ if (piece == 'p' || piece == 'P' || takepiece != 0) | |
+ halfmove = 0; | |
+ else | |
+ halfmove++; | |
+ | |
/* castling */ | |
if (piece == 'K' && y == 7 && y2 == 7 && x == 4) { | |
/* white: kingside castling: "e1g1" */ | |
@@ -514,8 +562,14 @@ main(int argc, char *argv[]) | |
s++; | |
} | |
+ /* a move by black increases the move number */ | |
+ if (side_to_move == 'b') | |
+ movenumber++; | |
+ | |
/* switch which side it is to move */ | |
side_to_move = side_to_move == 'b' ? 'w' : 'b'; | |
+ | |
+ /* TODO: reset enpassant square if applicable */ | |
} | |
} | |
/* highlight last move */ |