mirror of
https://github.com/lichess-org/dartchess.git
synced 2026-05-26 13:51:01 +00:00
Fix castling rights parsing
This commit is contained in:
+17
-17
@@ -10,7 +10,7 @@ import 'square_set.dart';
|
||||
abstract class Castles {
|
||||
/// Creates a new [Castles] instance.
|
||||
const factory Castles({
|
||||
required SquareSet unmovedRooks,
|
||||
required SquareSet castlingRights,
|
||||
Square? whiteRookQueenSide,
|
||||
Square? whiteRookKingSide,
|
||||
Square? blackRookQueenSide,
|
||||
@@ -22,7 +22,7 @@ abstract class Castles {
|
||||
}) = _Castles;
|
||||
|
||||
const Castles._({
|
||||
required this.unmovedRooks,
|
||||
required this.castlingRights,
|
||||
Square? whiteRookQueenSide,
|
||||
Square? whiteRookKingSide,
|
||||
Square? blackRookQueenSide,
|
||||
@@ -41,7 +41,7 @@ abstract class Castles {
|
||||
_blackPathKingSide = blackPathKingSide;
|
||||
|
||||
/// SquareSet of rooks that have not moved yet.
|
||||
final SquareSet unmovedRooks;
|
||||
final SquareSet castlingRights;
|
||||
|
||||
final Square? _whiteRookQueenSide;
|
||||
final Square? _whiteRookKingSide;
|
||||
@@ -53,7 +53,7 @@ abstract class Castles {
|
||||
final SquareSet _blackPathKingSide;
|
||||
|
||||
static const standard = Castles(
|
||||
unmovedRooks: SquareSet.corners,
|
||||
castlingRights: SquareSet.corners,
|
||||
whiteRookQueenSide: Square.a1,
|
||||
whiteRookKingSide: Square.h1,
|
||||
blackRookQueenSide: Square.a8,
|
||||
@@ -65,7 +65,7 @@ abstract class Castles {
|
||||
);
|
||||
|
||||
static const empty = Castles(
|
||||
unmovedRooks: SquareSet.empty,
|
||||
castlingRights: SquareSet.empty,
|
||||
whitePathQueenSide: SquareSet.empty,
|
||||
whitePathKingSide: SquareSet.empty,
|
||||
blackPathQueenSide: SquareSet.empty,
|
||||
@@ -73,7 +73,7 @@ abstract class Castles {
|
||||
);
|
||||
|
||||
static const horde = Castles(
|
||||
unmovedRooks: SquareSet(0x8100000000000000),
|
||||
castlingRights: SquareSet(0x8100000000000000),
|
||||
blackRookKingSide: Square.h8,
|
||||
blackRookQueenSide: Square.a8,
|
||||
whitePathKingSide: SquareSet.empty,
|
||||
@@ -85,7 +85,7 @@ abstract class Castles {
|
||||
/// Creates a [Castles] instance from a [Setup].
|
||||
factory Castles.fromSetup(Setup setup) {
|
||||
Castles castles = Castles.empty;
|
||||
final rooks = setup.unmovedRooks & setup.board.rooks;
|
||||
final rooks = setup.castlingRights & setup.board.rooks;
|
||||
for (final side in Side.values) {
|
||||
final backrank = SquareSet.backrankOf(side);
|
||||
final king = setup.board.kingOf(side);
|
||||
@@ -161,7 +161,7 @@ abstract class Castles {
|
||||
/// Returns a new [Castles] instance with the given rook discarded.
|
||||
Castles discardRookAt(Square square) {
|
||||
return copyWith(
|
||||
unmovedRooks: unmovedRooks.withoutSquare(square),
|
||||
castlingRights: castlingRights.withoutSquare(square),
|
||||
whiteRookQueenSide:
|
||||
_whiteRookQueenSide == square ? null : _whiteRookQueenSide,
|
||||
whiteRookKingSide:
|
||||
@@ -176,7 +176,7 @@ abstract class Castles {
|
||||
/// Returns a new [Castles] instance with the given side discarded.
|
||||
Castles discardSide(Side side) {
|
||||
return copyWith(
|
||||
unmovedRooks: unmovedRooks.diff(SquareSet.backrankOf(side)),
|
||||
castlingRights: castlingRights.diff(SquareSet.backrankOf(side)),
|
||||
whiteRookQueenSide: side == Side.white ? null : _whiteRookQueenSide,
|
||||
whiteRookKingSide: side == Side.white ? null : _whiteRookKingSide,
|
||||
blackRookQueenSide: side == Side.black ? null : _blackRookQueenSide,
|
||||
@@ -193,7 +193,7 @@ abstract class Castles {
|
||||
.withoutSquare(king)
|
||||
.withoutSquare(rook);
|
||||
return copyWith(
|
||||
unmovedRooks: unmovedRooks.withSquare(rook),
|
||||
castlingRights: castlingRights.withSquare(rook),
|
||||
whiteRookQueenSide: side == Side.white && cs == CastlingSide.queen
|
||||
? rook
|
||||
: _whiteRookQueenSide,
|
||||
@@ -219,14 +219,14 @@ abstract class Castles {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Castles(unmovedRooks: ${unmovedRooks.toHexString()})';
|
||||
return 'Castles(castlingRights: ${castlingRights.toHexString()})';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is Castles &&
|
||||
other.unmovedRooks == unmovedRooks &&
|
||||
other.castlingRights == castlingRights &&
|
||||
other._whiteRookQueenSide == _whiteRookQueenSide &&
|
||||
other._whiteRookKingSide == _whiteRookKingSide &&
|
||||
other._blackRookQueenSide == _blackRookQueenSide &&
|
||||
@@ -238,7 +238,7 @@ abstract class Castles {
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
unmovedRooks,
|
||||
castlingRights,
|
||||
_whiteRookQueenSide,
|
||||
_whiteRookKingSide,
|
||||
_blackRookQueenSide,
|
||||
@@ -249,7 +249,7 @@ abstract class Castles {
|
||||
_blackPathKingSide);
|
||||
|
||||
Castles copyWith({
|
||||
SquareSet? unmovedRooks,
|
||||
SquareSet? castlingRights,
|
||||
Square? whiteRookQueenSide,
|
||||
Square? whiteRookKingSide,
|
||||
Square? blackRookQueenSide,
|
||||
@@ -287,7 +287,7 @@ Square kingCastlesTo(Side side, CastlingSide cs) => switch (side) {
|
||||
|
||||
class _Castles extends Castles {
|
||||
const _Castles({
|
||||
required super.unmovedRooks,
|
||||
required super.castlingRights,
|
||||
super.whiteRookQueenSide,
|
||||
super.whiteRookKingSide,
|
||||
super.blackRookQueenSide,
|
||||
@@ -300,7 +300,7 @@ class _Castles extends Castles {
|
||||
|
||||
@override
|
||||
Castles copyWith({
|
||||
SquareSet? unmovedRooks,
|
||||
SquareSet? castlingRights,
|
||||
Object? whiteRookQueenSide = _uniqueObjectInstance,
|
||||
Object? whiteRookKingSide = _uniqueObjectInstance,
|
||||
Object? blackRookQueenSide = _uniqueObjectInstance,
|
||||
@@ -311,7 +311,7 @@ class _Castles extends Castles {
|
||||
SquareSet? blackPathKingSide,
|
||||
}) {
|
||||
return _Castles(
|
||||
unmovedRooks: unmovedRooks ?? this.unmovedRooks,
|
||||
castlingRights: castlingRights ?? this.castlingRights,
|
||||
whiteRookQueenSide: whiteRookQueenSide == _uniqueObjectInstance
|
||||
? _whiteRookQueenSide
|
||||
: whiteRookQueenSide as Square?,
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'dart:math' as math;
|
||||
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
|
||||
import 'attacks.dart';
|
||||
import 'castles.dart';
|
||||
import 'debug.dart';
|
||||
import 'models.dart';
|
||||
import 'board.dart';
|
||||
import 'setup.dart';
|
||||
@@ -130,7 +131,7 @@ abstract class Position<T extends Position<T>> {
|
||||
board: board,
|
||||
pockets: pockets,
|
||||
turn: turn,
|
||||
unmovedRooks: castles.unmovedRooks,
|
||||
castlingRights: castles.castlingRights,
|
||||
epSquare: _legalEpSquare(),
|
||||
halfmoves: halfmoves,
|
||||
fullmoves: fullmoves,
|
||||
@@ -1739,7 +1740,7 @@ abstract class ThreeCheck extends Position<ThreeCheck> {
|
||||
return Setup(
|
||||
board: board,
|
||||
turn: turn,
|
||||
unmovedRooks: castles.unmovedRooks,
|
||||
castlingRights: castles.castlingRights,
|
||||
epSquare: _legalEpSquare(),
|
||||
halfmoves: halfmoves,
|
||||
fullmoves: fullmoves,
|
||||
|
||||
+35
-40
@@ -13,7 +13,7 @@ class Setup {
|
||||
required this.board,
|
||||
this.pockets,
|
||||
required this.turn,
|
||||
required this.unmovedRooks,
|
||||
required this.castlingRights,
|
||||
this.epSquare,
|
||||
required this.halfmoves,
|
||||
required this.fullmoves,
|
||||
@@ -73,12 +73,12 @@ class Setup {
|
||||
}
|
||||
|
||||
// Castling
|
||||
SquareSet unmovedRooks;
|
||||
SquareSet castlingRights;
|
||||
if (parts.isEmpty) {
|
||||
unmovedRooks = SquareSet.empty;
|
||||
castlingRights = SquareSet.empty;
|
||||
} else {
|
||||
final castlingPart = parts.removeAt(0);
|
||||
unmovedRooks = _parseCastlingFen(board, castlingPart);
|
||||
castlingRights = _parseCastlingFen(board, castlingPart);
|
||||
}
|
||||
|
||||
// En passant square
|
||||
@@ -131,7 +131,7 @@ class Setup {
|
||||
board: board,
|
||||
pockets: pockets,
|
||||
turn: turn,
|
||||
unmovedRooks: unmovedRooks,
|
||||
castlingRights: castlingRights,
|
||||
epSquare: epSquare,
|
||||
halfmoves: halfmoves,
|
||||
fullmoves: fullmoves,
|
||||
@@ -149,7 +149,7 @@ class Setup {
|
||||
final Side turn;
|
||||
|
||||
/// Unmoved rooks positions used to determine castling rights.
|
||||
final SquareSet unmovedRooks;
|
||||
final SquareSet castlingRights;
|
||||
|
||||
/// En passant target square.
|
||||
///
|
||||
@@ -169,7 +169,7 @@ class Setup {
|
||||
static const standard = Setup(
|
||||
board: Board.standard,
|
||||
turn: Side.white,
|
||||
unmovedRooks: SquareSet.corners,
|
||||
castlingRights: SquareSet.corners,
|
||||
halfmoves: 0,
|
||||
fullmoves: 1,
|
||||
);
|
||||
@@ -181,7 +181,7 @@ class Setup {
|
||||
String get fen => [
|
||||
board.fen + (pockets != null ? _makePockets(pockets!) : ''),
|
||||
turnLetter,
|
||||
_makeCastlingFen(board, unmovedRooks),
|
||||
_makeCastlingFen(board, castlingRights),
|
||||
if (epSquare != null) epSquare!.name else '-',
|
||||
if (remainingChecks != null) _makeRemainingChecks(remainingChecks!),
|
||||
math.max(0, math.min(halfmoves, 9999)),
|
||||
@@ -194,7 +194,7 @@ class Setup {
|
||||
other is Setup &&
|
||||
other.board == board &&
|
||||
other.turn == turn &&
|
||||
other.unmovedRooks == unmovedRooks &&
|
||||
other.castlingRights == castlingRights &&
|
||||
other.epSquare == epSquare &&
|
||||
other.halfmoves == halfmoves &&
|
||||
other.fullmoves == fullmoves;
|
||||
@@ -204,7 +204,7 @@ class Setup {
|
||||
int get hashCode => Object.hash(
|
||||
board,
|
||||
turn,
|
||||
unmovedRooks,
|
||||
castlingRights,
|
||||
epSquare,
|
||||
halfmoves,
|
||||
fullmoves,
|
||||
@@ -312,43 +312,38 @@ Pockets _parsePockets(String pocketPart) {
|
||||
}
|
||||
|
||||
SquareSet _parseCastlingFen(Board board, String castlingPart) {
|
||||
SquareSet unmovedRooks = SquareSet.empty;
|
||||
SquareSet castlingRights = SquareSet.empty;
|
||||
if (castlingPart == '-') {
|
||||
return unmovedRooks;
|
||||
return castlingRights;
|
||||
}
|
||||
for (int i = 0; i < castlingPart.length; i++) {
|
||||
final c = castlingPart[i];
|
||||
for (final rune in castlingPart.runes) {
|
||||
final c = String.fromCharCode(rune);
|
||||
final lower = c.toLowerCase();
|
||||
final color = c == lower ? Side.black : Side.white;
|
||||
final backrankMask = SquareSet.backrankOf(color);
|
||||
final backrank = backrankMask & board.bySide(color);
|
||||
|
||||
Iterable<Square> candidates;
|
||||
if (lower == 'q') {
|
||||
candidates = backrank.squares;
|
||||
} else if (lower == 'k') {
|
||||
candidates = backrank.squaresReversed;
|
||||
} else if ('a'.compareTo(lower) <= 0 && lower.compareTo('h') <= 0) {
|
||||
candidates =
|
||||
(SquareSet.fromFile(File(lower.codeUnitAt(0) - 'a'.codeUnitAt(0))) &
|
||||
backrank)
|
||||
.squares;
|
||||
final lowerCode = lower.codeUnitAt(0);
|
||||
final side = c == lower ? Side.black : Side.white;
|
||||
final rank = side == Side.white ? Rank.first : Rank.eighth;
|
||||
if ('a'.codeUnitAt(0) <= lowerCode && lowerCode <= 'h'.codeUnitAt(0)) {
|
||||
castlingRights = castlingRights.withSquare(
|
||||
Square.fromCoords(File(lowerCode - 'a'.codeUnitAt(0)), rank));
|
||||
} else if (lower == 'k' || lower == 'q') {
|
||||
final rooksAndKings = (board.bySide(side) & SquareSet.backrankOf(side)) &
|
||||
(board.rooks | board.kings);
|
||||
final candidate = lower == 'k'
|
||||
? rooksAndKings.squares.lastOrNull
|
||||
: rooksAndKings.squares.firstOrNull;
|
||||
castlingRights = castlingRights.withSquare(
|
||||
candidate != null && board.rooks.has(candidate)
|
||||
? candidate
|
||||
: Square.fromCoords(lower == 'k' ? File.h : File.a, rank));
|
||||
} else {
|
||||
throw const FenException(IllegalFenCause.castling);
|
||||
}
|
||||
for (final square in candidates) {
|
||||
if (board.kings.has(square)) break;
|
||||
if (board.rooks.has(square)) {
|
||||
unmovedRooks = unmovedRooks.withSquare(square);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((const SquareSet.fromRank(Rank.first) & unmovedRooks).size > 2 ||
|
||||
(const SquareSet.fromRank(Rank.eighth) & unmovedRooks).size > 2) {
|
||||
if (Side.values.any((color) =>
|
||||
SquareSet.backrankOf(color).intersect(castlingRights).size > 2)) {
|
||||
throw const FenException(IllegalFenCause.castling);
|
||||
}
|
||||
return unmovedRooks;
|
||||
return castlingRights;
|
||||
}
|
||||
|
||||
String _makePockets(Pockets pockets) {
|
||||
@@ -363,14 +358,14 @@ String _makePockets(Pockets pockets) {
|
||||
return '[${wPart.toUpperCase()}$bPart]';
|
||||
}
|
||||
|
||||
String _makeCastlingFen(Board board, SquareSet unmovedRooks) {
|
||||
String _makeCastlingFen(Board board, SquareSet castlingRights) {
|
||||
final buffer = StringBuffer();
|
||||
for (final color in Side.values) {
|
||||
final backrank = SquareSet.backrankOf(color);
|
||||
final king = board.kingOf(color);
|
||||
final candidates =
|
||||
board.byPiece(Piece(color: color, role: Role.rook)) & backrank;
|
||||
for (final rook in (unmovedRooks & candidates).squaresReversed) {
|
||||
for (final rook in (castlingRights & backrank).squaresReversed) {
|
||||
if (rook == candidates.first && king != null && rook < king) {
|
||||
buffer.write(color == Side.white ? 'Q' : 'q');
|
||||
} else if (rook == candidates.last && king != null && king < rook) {
|
||||
|
||||
@@ -18,7 +18,7 @@ void main() {
|
||||
});
|
||||
test('fromSetup', () {
|
||||
final castles = Castles.fromSetup(Setup.standard);
|
||||
expect(castles.unmovedRooks, SquareSet.corners);
|
||||
expect(castles.castlingRights, SquareSet.corners);
|
||||
expect(castles, Castles.standard);
|
||||
|
||||
expect(castles.rookOf(Side.white, CastlingSide.queen), Square.a1);
|
||||
|
||||
+75
-5
@@ -13,12 +13,12 @@ void main() {
|
||||
|
||||
test('Chess.toString()', () {
|
||||
expect(Chess.initial.toString(),
|
||||
'Chess(board: rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR, turn: Side.white, castles: Castles(unmovedRooks: 0x8100000000000081), halfmoves: 0, fullmoves: 1)');
|
||||
'Chess(board: rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR, turn: Side.white, castles: Castles(castlingRights: 0x8100000000000081), halfmoves: 0, fullmoves: 1)');
|
||||
});
|
||||
|
||||
test('Antichess.toString()', () {
|
||||
expect(Antichess.initial.toString(),
|
||||
'Antichess(board: $kInitialBoardFEN, turn: Side.white, castles: Castles(unmovedRooks: 0), halfmoves: 0, fullmoves: 1)');
|
||||
'Antichess(board: $kInitialBoardFEN, turn: Side.white, castles: Castles(castlingRights: 0), halfmoves: 0, fullmoves: 1)');
|
||||
});
|
||||
|
||||
test('ply', () {
|
||||
@@ -397,6 +397,76 @@ void main() {
|
||||
expect(pos.legalMovesOf(Square.e1), const SquareSet(0x00000000000000A9));
|
||||
});
|
||||
|
||||
test('castling chess960 legal moves', () {
|
||||
for (final fen in [
|
||||
'1qr2k1r/pppppppp/6n1/8/8/5BN1/PPPPPPPP/1QR2K1R w KQkq - 0 1',
|
||||
'1qr2k1r/pppppppp/6n1/8/8/5BN1/PPPPPPPP/1QR2K1R w CHch - 0 1',
|
||||
]) {
|
||||
final pos = Chess.fromSetup(Setup.parseFen(fen));
|
||||
expect(pos.legalMovesOf(Square.f1), makeSquareSet('''
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
. . 1 . 1 . 1 1
|
||||
'''));
|
||||
}
|
||||
|
||||
for (final fen in [
|
||||
'1qr2k1r/pppppppp/6n1/8/8/5BN1/PPPPPPPP/1QR2K1R b KQkq - 0 1',
|
||||
'1qr2k1r/pppppppp/6n1/8/8/5BN1/PPPPPPPP/1QR2K1R b CHch - 0 1',
|
||||
]) {
|
||||
final pos = Chess.fromSetup(Setup.parseFen(fen));
|
||||
expect(pos.legalMovesOf(Square.f8), makeSquareSet('''
|
||||
. . 1 . 1 . 1 1
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
'''));
|
||||
}
|
||||
|
||||
for (final fen in [
|
||||
'1qr2k1r/pppppppp/6n1/8/8/5BN1/PPPPPPPP/1QR2K1R w Qkq - 0 1',
|
||||
'1qr2k1r/pppppppp/6n1/8/8/5BN1/PPPPPPPP/1QR2K1R w Cch - 0 1',
|
||||
]) {
|
||||
final pos = Chess.fromSetup(Setup.parseFen(fen));
|
||||
expect(pos.legalMovesOf(Square.f1), makeSquareSet('''
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
. . 1 . 1 . 1 .
|
||||
'''));
|
||||
}
|
||||
|
||||
for (final fen in [
|
||||
'1qr2k1r/pppppppp/6n1/8/8/5BN1/PPPPPPPP/1QR2K1R b k - 0 1',
|
||||
'1qr2k1r/pppppppp/6n1/8/8/5BN1/PPPPPPPP/1QR2K1R b h - 0 1',
|
||||
]) {
|
||||
final pos = Chess.fromSetup(Setup.parseFen(fen));
|
||||
expect(pos.legalMovesOf(Square.f8), makeSquareSet('''
|
||||
. . . . 1 . 1 1
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
. . . . . . . .
|
||||
'''));
|
||||
}
|
||||
});
|
||||
|
||||
test('isCheck', () {
|
||||
expect(
|
||||
Chess.fromSetup(Setup.parseFen(
|
||||
@@ -598,7 +668,7 @@ void main() {
|
||||
CastlingSide.queen: Square.a1,
|
||||
CastlingSide.king: null
|
||||
})));
|
||||
expect(pos.castles.unmovedRooks.has(Square.h1), false);
|
||||
expect(pos.castles.castlingRights.has(Square.h1), false);
|
||||
});
|
||||
|
||||
test('capturing a rook removes castling right', () {
|
||||
@@ -607,7 +677,7 @@ void main() {
|
||||
.play(const NormalMove(from: Square.g7, to: Square.a1));
|
||||
expect(pos.castles.rookOf(Side.white, CastlingSide.queen), isNull);
|
||||
expect(pos.castles.rookOf(Side.white, CastlingSide.king), Square.h1);
|
||||
expect(pos.castles.unmovedRooks.has(Square.a1), false);
|
||||
expect(pos.castles.castlingRights.has(Square.a1), false);
|
||||
});
|
||||
|
||||
test('king captures unmoved rook', () {
|
||||
@@ -639,7 +709,7 @@ void main() {
|
||||
expect(pos.board.pieceAt(Square.g1), Piece.whiteKing);
|
||||
expect(pos.board.pieceAt(Square.f1), Piece.whiteRook);
|
||||
expect(
|
||||
pos.castles.unmovedRooks
|
||||
pos.castles.castlingRights
|
||||
.isIntersected(const SquareSet.fromRank(Rank.first)),
|
||||
false);
|
||||
expect(pos.castles.rookOf(Side.white, CastlingSide.king), isNull);
|
||||
|
||||
@@ -14,18 +14,18 @@ void main() {
|
||||
test('parse castling fen, standard initial board', () {
|
||||
expect(
|
||||
Setup.parseFen('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq')
|
||||
.unmovedRooks,
|
||||
.castlingRights,
|
||||
SquareSet.corners);
|
||||
expect(
|
||||
Setup.parseFen('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w -')
|
||||
.unmovedRooks,
|
||||
.castlingRights,
|
||||
SquareSet.empty);
|
||||
});
|
||||
|
||||
test('parse castling fen, shredder notation', () {
|
||||
expect(
|
||||
Setup.parseFen('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w HAha')
|
||||
.unmovedRooks,
|
||||
.castlingRights,
|
||||
SquareSet.corners);
|
||||
});
|
||||
|
||||
@@ -33,7 +33,7 @@ void main() {
|
||||
expect(
|
||||
() =>
|
||||
Setup.parseFen('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w BGL')
|
||||
.unmovedRooks,
|
||||
.castlingRights,
|
||||
throwsA(predicate(
|
||||
(e) => e is FenException && e.cause == IllegalFenCause.castling)));
|
||||
});
|
||||
@@ -52,7 +52,7 @@ void main() {
|
||||
expect(setup, Setup.standard);
|
||||
expect(setup.board, Board.standard);
|
||||
expect(setup.turn, Side.white);
|
||||
expect(setup.unmovedRooks, SquareSet.corners);
|
||||
expect(setup.castlingRights, SquareSet.corners);
|
||||
expect(setup.epSquare, null);
|
||||
expect(setup.halfmoves, 0);
|
||||
expect(setup.fullmoves, 1);
|
||||
@@ -62,7 +62,7 @@ void main() {
|
||||
final setup = Setup.parseFen(kInitialBoardFEN);
|
||||
expect(setup.board, Board.standard);
|
||||
expect(setup.turn, Side.white);
|
||||
expect(setup.unmovedRooks, SquareSet.empty);
|
||||
expect(setup.castlingRights, SquareSet.empty);
|
||||
expect(setup.epSquare, null);
|
||||
expect(setup.halfmoves, 0);
|
||||
expect(setup.fullmoves, 1);
|
||||
@@ -95,6 +95,7 @@ void main() {
|
||||
'rnb1kbnr/ppp1pppp/2Pp2PP/1P3PPP/PPP1PPPP/PPP1PPPP/PPP1PPP1/PPPqPP2 w kq - 0 1',
|
||||
'5b1r/1p5p/4ppp1/4Bn2/1PPP1PP1/4P2P/3k4/4K2R w K - 1 1',
|
||||
'rnbqkb1r/p1p1nppp/2Pp4/3P1PP1/PPPPPP1P/PPP1PPPP/PPPnbqkb/PPPPPPPP w ha - 1 6',
|
||||
'rnbNRbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQhb - 2 3',
|
||||
]) {
|
||||
final setup = Setup.parseFen(fen);
|
||||
expect(setup.fen, fen);
|
||||
|
||||
Reference in New Issue
Block a user