fen.c: improve castling for chess960 - 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 35cfce88175a31ca9b1db67e70575f66182d8ab2
 (DIR) parent cb828aa3fa341d3af5e9338132497cf49671369f
 (HTM) Author: Hiltjo Posthuma <hiltjo@codemadness.org>
       Date:   Thu, 21 Dec 2023 22:19:16 +0100
       
       fen.c: improve castling for chess960
       
       In chess960 you can castle right next to the king also.
       
       This is handled in the code by "taking a piece", although this is of course
       your own piece.
       
       Note that this doesn't reset the halfmove counter.
       
       Diffstat:
         M fen.c                               |      86 +++++++++++++++++++++----------
       
       1 file changed, 58 insertions(+), 28 deletions(-)
       ---
 (DIR) diff --git a/fen.c b/fen.c
       @@ -39,6 +39,20 @@ isvalidsquare(int x, int y)
        }
        
        int
       +iswhitepiece(int piece)
       +{
       +        return piece == 'K' || piece == 'Q' || piece == 'R' ||
       +               piece == 'B' || piece == 'N' || piece == 'P';
       +}
       +
       +int
       +isblackpiece(int piece)
       +{
       +        return piece == 'k' || piece == 'q' || piece == 'r' ||
       +               piece == 'b' || piece == 'n' || piece == 'p';
       +}
       +
       +int
        isvalidpiece(int c)
        {
                static char pieces[] = "PNBRQKpnbrqk";
       @@ -535,33 +549,40 @@ parsemoves(const char *moves)
                                squaretoxy(square, &x, &y);
                                piece = getpiece(x, y);
        
       -                        place(0, x, y); /* clear square */
       -
       -                        /* place piece at new location */
       +                        /* target location */
                                square[0] = *s;
                                square[1] = *(s + 1);
                                squaretoxy(square, &x2, &y2);
       +
       +                        /* place piece at new location */
       +                        place(0, x, y); /* clear previous square */
       +                        /* take piece (can be your own) */
                                takepiece = getpiece(x2, y2);
       -                        place(piece, x2, y2);
       +
                                s += 2;
        
                                /* if pawn move or taken a piece increase halfmove counter */
       -                        if (piece == 'p' || piece == 'P' || takepiece != 0)
       +                        if (piece == 'p' || piece == 'P' ||
       +                            (side_to_move == 'w' && isblackpiece(takepiece)) ||
       +                            (side_to_move == 'b' && iswhitepiece(takepiece)))
                                        halfmove = 0;
                                else
                                        halfmove++;
        
                                /* castling */
                                if (piece == 'K' && y == 7 && y2 == 7) {
       -                                /* white: kingside castling: "e1g1" */
       -                                if (x2 >= x + 2) { /* moved more than 1 square */
       -                                        place('R', x2 - 1, y2);
       -                                        x2 = 7;
       -                                        y2 = 7;
       -                                        place(0, x2, y2); /* clear rook square */
       -                                } else if (x2 <= x - 2) { /* moved more than 1 square */
       -                                        /* white: queenside castling: "e1c1" */
       -                                        for (i = x2 - 1; i > 0; i--) {
       +                                /* white: kingside castling */
       +                                if (x2 > x + 1 || takepiece == 'R') {
       +                                        for (i = x2; i < 8; i++) {
       +                                                if (getpiece(i, y2) == 'R') {
       +                                                        place(0, i, y2); /* clear rook square */
       +                                                        place('R', x2 - 1, y2); /* next to king */
       +                                                        break;
       +                                                }
       +                                        }
       +                                } else if (x2 < x - 1 || takepiece == 'R') {
       +                                        /* white: queenside castling */
       +                                        for (i = x2; i >= 0; i--) {
                                                        if (getpiece(i, y2) == 'R') {
                                                                place('R', x2 + 1, y2); /* next to king */
                                                                place(0, i, y2); /* clear rook square */
       @@ -570,18 +591,24 @@ parsemoves(const char *moves)
                                                }
                                        }
                                } else if (piece == 'k' && y == 0 && y2 == 0) {
       -                                /* black: kingside castling: "e8g8" */
       -                                if (x2 == 6) {
       -                                        place('r', x2 - 1, y2);
       -                                        x2 = 7;
       -                                        y2 = 0;
       -                                        place(0, x2, y2); /* clear rook square */
       -                                } else if (x2 == 2) {
       -                                        /* black: queenside castling: "e8c8" */
       -                                        place('r', x2 + 1, y2);
       -                                        x2 = 0;
       -                                        y2 = 0;
       -                                        place(0, x2, y2); /* clear rook square */
       +                                /* black: kingside castling */
       +                                if (x2 > x + 1 || takepiece == 'r') {
       +                                        for (i = x2; i < 8; i++) {
       +                                                if (getpiece(i, y2) == 'r') {
       +                                                        place(0, i, y2); /* clear rook square */
       +                                                        place('r', x2 - 1, y2); /* next to king */
       +                                                        break;
       +                                                }
       +                                        }
       +                                } else if (x2 < x - 1 || takepiece == 'R') {
       +                                        /* black: queenside castling */
       +                                        for (i = x2; i >= 0; i--) {
       +                                                if (getpiece(i, y2) == 'r') {
       +                                                        place('r', x2 + 1, y2); /* next to king */
       +                                                        place(0, i, y2); /* clear rook square */
       +                                                        break;
       +                                                }
       +                                        }
                                        }
                                }
        
       @@ -591,7 +618,7 @@ parsemoves(const char *moves)
                                } else if (piece == 'k') {
                                        black_can_castle[0] = black_can_castle[1] = 0;
                                } else if (piece == 'R' && y == 7) {
       -                                for (i = 0; i < 7; i++) {
       +                                for (i = 0; i < 8; i++) {
                                                if (getpiece(i, y) == 'K') {
                                                        if (i < x)
                                                                white_can_castle[0] = 0;
       @@ -601,7 +628,7 @@ parsemoves(const char *moves)
                                                }
                                        }
                                } else if (piece == 'r' && y == 0) {
       -                                for (i = 0; i < 7; i++) {
       +                                for (i = 0; i < 8; i++) {
                                                if (getpiece(i, y) == 'k') {
                                                        if (i > x)
                                                                black_can_castle[1] = 0;
       @@ -634,6 +661,9 @@ parsemoves(const char *moves)
                                        }
                                }
        
       +                        /* place piece */
       +                        place(piece, x2, y2);
       +
                                /* possible promotion: queen, knight, bishop */
                                if (*s == 'q' || *s == 'n' || *s == 'b') {
                                        if (side_to_move == 'w')