squares.emplace_back(CharSquare(r, c));
return squares;
}
- /// Checks if a given character is on a given rank index
- bool is_piece_on_rank(char piece, int rowIdx) const {
- for (int f = 0; f < nbFiles; ++f)
- if (get_piece(rowIdx, f) == piece)
- return true;
- return false;
- }
friend std::ostream& operator<<(std::ostream& os, const CharBoard& board);
};
}
}
-inline Validation check_castling_rank(const std::array<std::string, 2>& castlingInfoSplitted, const CharBoard& board, const Variant* v) {
+inline Validation check_castling_rank(const std::array<std::string, 2>& castlingInfoSplitted, const CharBoard& board,
+ const std::array<CharSquare, 2>& kingPositions, const Variant* v) {
for (Color c : {WHITE, BLACK})
{
- for (char charPiece : {v->pieceToChar[make_piece(c, v->castlingKingPiece)],
- v->pieceToChar[make_piece(c, v->castlingRookPiece)]})
+ const Rank castlingRank = relative_rank(c, v->castlingRank, v->maxRank);
+ char rookChar = v->pieceToChar[make_piece(c, v->castlingRookPiece)];
+ for (char castlingFlag : castlingInfoSplitted[c])
{
- if (castlingInfoSplitted[c].size() == 0)
- continue;
- const Rank castlingRank = relative_rank(c, v->castlingRank, v->maxRank);
- if (!board.is_piece_on_rank(charPiece, castlingRank))
+ if (tolower(castlingFlag) == 'k' || tolower(castlingFlag) == 'q')
+ {
+ if (kingPositions[c].rowIdx != castlingRank)
+ {
+ std::cerr << "The " << color_to_string(c) << " king must be on rank " << castlingRank << " if castling is enabled for " << color_to_string(c) << "." << std::endl;
+ return NOK;
+ }
+ bool kingside = tolower(castlingFlag) == 'k';
+ bool castlingRook = false;
+ for (int f = kingside ? board.get_nb_files() - 1 : 0; f != kingPositions[c].fileIdx; kingside ? f-- : f++)
+ if (board.get_piece(castlingRank, f) == rookChar)
+ {
+ castlingRook = true;
+ break;
+ }
+ if (!castlingRook)
+ {
+ std::cerr << "No castling rook for flag " << castlingFlag << std::endl;
+ return NOK;
+ }
+ }
+ else if (board.get_piece(castlingRank, tolower(castlingFlag) - 'a') == ' ')
{
- std::cerr << "The " << color_to_string(c) << " king and rook must be on rank " << castlingRank << " if castling is enabled for " << color_to_string(c) << "." << std::endl;
+ std::cerr << "No gating piece for flag " << castlingFlag << std::endl;
return NOK;
}
}
CharBoard startBoard(board.get_nb_ranks(), board.get_nb_files());
fill_char_board(startBoard, v->startFen, validSpecialCharacters, v);
- // skip check for gating variants to avoid confusion with gating squares
- if (!v->gating && check_castling_rank(castlingInfoSplitted, board, v) == NOK)
+ // Check pieces present on castling rank against castling/gating rights
+ if (check_castling_rank(castlingInfoSplitted, board, kingPositions, v) == NOK)
return FEN_INVALID_CASTLING_INFO;
// only check exact squares if starting position of castling pieces is known
"rnbqkbnr/pppppppp/7/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", # invalid file count
"rnbqkbnr/pppppppp/9/7/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", # invalid file count
"rnbqkbnr/pppppppp/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", # invalid rank count
- "1nbqkbn1/pppppppp/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", # missing castling rook
- "rnbqkbnr/pppppppp/8/8/4K3/PPPPPPPP/RNBQ1BNR w KQkq - 0 1", # king not on castling rank
- "rnbqkbnr/pppppppp/8/8/RNBQKBNR/PPPPPPPP/8 w KQkq - 0 1", # not on castling rank
- "8/pppppppp/rnbqkbnr/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", # not on castling rank
+ "rnbqkbn1/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", # missing castling rook
+ "1nbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", # missing castling rook
+ "rnbqkbnr/pppppppp/8/8/8/4K3/PPPPPPPP/RNBQ1BNR w KQkq - 0 1", # king not on castling rank
+ "rnbqkbnr/pppppppp/8/8/8/RNBQKBNR/PPPPPPPP/8 w KQkq - 0 1", # not on castling rank
+ "8/pppppppp/rnbqkbnr/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", # not on castling rank
),
"atomic": (
"rnbqkbnr/pppppppp/8/8/8/RNBQKBNR/PPPPPPPP/8 w KQkq - 0 1", # wrong castling rank
),
"shako": {
"c8c/ernbqkbnre/pppppppppp/10/10/10/10/PPPPPPPPPP/C8C/ERNBQKBNRE w KQkq - 0 1", # not on castling rank
+ },
+ "seirawan": {
+ "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQK1NR[HEhe] w KQBCDFGkqbcdfg - 0 1", # white gating flag
+ "rnbqkb1r/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR[HEhe] w KQBCDFGkqbcdfg - 0 1", # black gating flag
}
}