commit 35cfce88175a31ca9b1db67e70575f66182d8ab2
parent cb828aa3fa341d3af5e9338132497cf49671369f
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(-)
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')