Skip to content

Commit

Permalink
Fix FEN parsing for S-Chess
Browse files Browse the repository at this point in the history
Closes #855.
  • Loading branch information
ianfab committed Jan 9, 2025
1 parent 239475b commit f114eed
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 6 deletions.
14 changes: 8 additions & 6 deletions src/position.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,25 +384,27 @@ Position& Position::set(const Variant* v, const string& fenStr, bool isChess960,
: make_square(castling_king_file(), castling_rank(c));
// Skip invalid castling rights
if (!(castlingKings & st->castlingKingSquare[c]))
{
st->castlingKingSquare[c] = SQ_NONE;
continue;
}
}

// Set gates (and skip castling rights)
if (gating())
{
st->gatesBB[c] |= rsq;
if (token == 'K' || token == 'Q')
// Only add gates for occupied squares
if (pieces(c) & rsq)
st->gatesBB[c] |= rsq;
if ((token == 'K' || token == 'Q') && st->castlingKingSquare[c] != SQ_NONE)
st->gatesBB[c] |= st->castlingKingSquare[c];
// Do not set castling rights for gates unless there are no pieces in hand,
// which means that the file is referring to a chess960 castling right.
else if (!seirawan_gating() || count_in_hand(c, ALL_PIECES) > 0 || captures_to_hand())
continue;
}

if (castling_enabled() && (castling_rook_pieces(c) & type_of(piece_on(rsq))) && color_of(piece_on(rsq)) == c)
// Only add castling right if both king and rook are on expected squares
if ( castling_enabled()
&& st->castlingKingSquare[c] != SQ_NONE
&& (castling_rook_pieces(c) & type_of(piece_on(rsq))) && color_of(piece_on(rsq)) == c)
set_castling_right(c, rsq);
}

Expand Down
11 changes: 11 additions & 0 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,11 @@ def test_legal_moves(self):
result = sf.legal_moves("shogun", SHOGUN, ["c2c4", "b8c6", "b2b4", "b7b5", "c4b5", "c6b8"])
self.assertIn("b5b6+", result)

# Seirawan gating but no castling
fen = "rnbq3r/pp2bkpp/8/2p1p2K/2p1P3/8/PPPP1PPP/RNB4R[EHeh] b ABCHabcdh - 0 10"
result = sf.legal_moves("seirawan", fen, [])
self.assertIn("c8g4h", result)

# In Cannon Shogi the FGC and FSC can also move one square diagonally and, besides,
# move or capture two squares diagonally, by leaping an adjacent piece.
fen = "lnsg1gsnl/1rc1kuab1/p1+A1p1p1p/3P5/6i2/6P2/P1P1P3P/1B1U1ICR1/LNSGKGSNL[] w - - 1 3"
Expand Down Expand Up @@ -460,6 +465,12 @@ def test_get_fen(self):
result = sf.get_fen("seirawan", fen0, ["e8g8"])
self.assertEqual(result, fen1)

# handle invalid castling/gating flags
fen0 = "rnbq3r/pp2bkpp/8/2p1p2K/2p1P3/8/PPPP1PPP/RNB4R[EHeh] b QBCEHabcdk - 0 10"
fen1 = "rnbq3r/pp2bkpp/8/2p1p2K/2p1P3/8/PPPP1PPP/RNB4R[EHeh] b ABCHabcdh - 0 10"
result = sf.get_fen("seirawan", fen0, [])
self.assertEqual(result, fen1)

result = sf.get_fen("chess", CHESS, [], True, False, False)
self.assertEqual(result, CHESS960)

Expand Down

0 comments on commit f114eed

Please sign in to comment.