commit 132c4a50aae9c410bf3b505f4c61b322c388cf83
parent 29822d687c7eed634e2fd6b480ddbf84cbabf4c2
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
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 side */
-static int black_can_castle[2] = { 0, 0 }; /* allow king side, allow queen side */
+static int white_can_castle[2] = { 0, 0 }; /* allow king side, allow queen side? */
+static int black_can_castle[2] = { 0, 0 }; /* allow king side, allow queen side? */
+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 counter */
+ /* 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 */