improve and extend FEN parsing and FEN output - chess-puzzles - chess puzzle book generator
 (HTM) git clone git://git.codemadness.org/chess-puzzles
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 132c4a50aae9c410bf3b505f4c61b322c388cf83
 (DIR) parent 29822d687c7eed634e2fd6b480ddbf84cbabf4c2
 (HTM) 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(-)
       ---
 (DIR) 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 */