chess-puzzles

chess puzzle book generator
git clone git://git.codemadness.org/chess-puzzles
Log | Files | Refs | README | LICENSE

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:
Mfen_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 */