mirror of
https://github.com/lichess-org/dartchess.git
synced 2026-05-26 13:51:01 +00:00
Document legalMoves castling format
Re-introduce `makeLegalMoves` to export legal moves in a convenient format. Closes #33
This commit is contained in:
@@ -13,3 +13,4 @@ export 'src/setup.dart';
|
||||
export 'src/position.dart';
|
||||
export 'src/debug.dart';
|
||||
export 'src/pgn.dart';
|
||||
export 'src/utils.dart';
|
||||
|
||||
+10
-1
@@ -7,6 +7,7 @@ import 'models.dart';
|
||||
import 'board.dart';
|
||||
import 'setup.dart';
|
||||
import 'square_set.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
/// A base class for playable chess or chess variant positions.
|
||||
///
|
||||
@@ -181,6 +182,14 @@ abstract class Position<T extends Position<T>> {
|
||||
}
|
||||
|
||||
/// Gets all the legal moves of this position.
|
||||
///
|
||||
/// Returns a [SquareSet] of all the legal moves for each [Square].
|
||||
///
|
||||
/// In order to support Chess960, the castling move format is encoded as the
|
||||
/// king-to-rook move only.
|
||||
///
|
||||
/// Use the [makeLegalMoves] helper to get all the legal moves including alternative
|
||||
/// castling moves.
|
||||
IMap<Square, SquareSet> get legalMoves {
|
||||
final context = _makeContext();
|
||||
if (context.isVariantEnd) return IMap(const {});
|
||||
@@ -193,7 +202,7 @@ abstract class Position<T extends Position<T>> {
|
||||
/// Gets all the legal drops of this position.
|
||||
SquareSet get legalDrops => SquareSet.empty;
|
||||
|
||||
/// SquareSet of pieces giving check.
|
||||
/// Square set of pieces giving check.
|
||||
SquareSet get checkers {
|
||||
final king = board.kingOf(turn);
|
||||
return king != null ? kingAttackers(king, turn.opposite) : SquareSet.empty;
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
|
||||
|
||||
import 'models.dart';
|
||||
import 'position.dart';
|
||||
|
||||
/// Returns all the legal moves of the [Position] in a convenient format.
|
||||
///
|
||||
/// Includes both possible representations of castling moves (unless `chess960` is true).
|
||||
IMap<Square, ISet<Square>> makeLegalMoves(
|
||||
Position pos, {
|
||||
bool isChess960 = false,
|
||||
}) {
|
||||
final Map<Square, ISet<Square>> result = {};
|
||||
for (final entry in pos.legalMoves.entries) {
|
||||
final dests = entry.value.squares;
|
||||
if (dests.isNotEmpty) {
|
||||
final from = entry.key;
|
||||
final destSet = dests.toSet();
|
||||
if (!isChess960 &&
|
||||
from == pos.board.kingOf(pos.turn) &&
|
||||
entry.key.file == 4) {
|
||||
if (dests.contains(Square.a1)) {
|
||||
destSet.add(Square.c1);
|
||||
} else if (dests.contains(Square.a8)) {
|
||||
destSet.add(Square.c8);
|
||||
}
|
||||
if (dests.contains(Square.h1)) {
|
||||
destSet.add(Square.g1);
|
||||
} else if (dests.contains(Square.h8)) {
|
||||
destSet.add(Square.g8);
|
||||
}
|
||||
}
|
||||
result[from] = ISet(destSet);
|
||||
}
|
||||
}
|
||||
return IMap(result);
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
import 'package:dartchess/dartchess.dart';
|
||||
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
test('makeLegalMoves with Kh8', () {
|
||||
final setup = Setup.parseFen(
|
||||
'r1bq1r2/3n2k1/p1p1pp2/3pP2P/8/PPNB2Q1/2P2P2/R3K3 b Q - 1 22',
|
||||
);
|
||||
final pos = Chess.fromSetup(setup);
|
||||
final moves = makeLegalMoves(pos);
|
||||
expect(moves[Square.g7], contains(Square.h8));
|
||||
expect(moves[Square.g7], isNot(contains(Square.g8)));
|
||||
});
|
||||
|
||||
test('makeLegalMoves with regular castle', () {
|
||||
final wtm =
|
||||
Chess.fromSetup(Setup.parseFen('r3k2r/8/8/8/8/8/8/R3K2R w KQkq - 0 1'));
|
||||
expect(
|
||||
makeLegalMoves(wtm)[Square.e1],
|
||||
equals(
|
||||
{
|
||||
Square.a1,
|
||||
Square.c1,
|
||||
Square.d1,
|
||||
Square.d2,
|
||||
Square.e2,
|
||||
Square.f1,
|
||||
Square.f2,
|
||||
Square.g1,
|
||||
Square.h1,
|
||||
},
|
||||
),
|
||||
);
|
||||
expect(makeLegalMoves(wtm)[Square.e8], null);
|
||||
|
||||
final btm =
|
||||
Chess.fromSetup(Setup.parseFen('r3k2r/8/8/8/8/8/8/R3K2R b KQkq - 0 1'));
|
||||
expect(
|
||||
makeLegalMoves(btm)[Square.e8],
|
||||
equals({
|
||||
Square.a8,
|
||||
Square.c8,
|
||||
Square.d7,
|
||||
Square.d8,
|
||||
Square.e7,
|
||||
Square.f7,
|
||||
Square.f8,
|
||||
Square.g8,
|
||||
Square.h8,
|
||||
}),
|
||||
);
|
||||
expect(makeLegalMoves(btm)[Square.e1], null);
|
||||
});
|
||||
|
||||
test('makeLegalMoves with chess960 castle', () {
|
||||
final pos = Chess.fromSetup(
|
||||
Setup.parseFen(
|
||||
'rk2r3/pppbnppp/3p2n1/P2Pp3/4P2q/R5NP/1PP2PP1/1KNQRB2 b Kkq - 0 1',
|
||||
),
|
||||
);
|
||||
expect(
|
||||
makeLegalMoves(pos, isChess960: true)[Square.b8],
|
||||
equals(ISet(const {Square.a8, Square.c8, Square.e8})),
|
||||
);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user