mirror of
https://github.com/lichess-org/dartchess.git
synced 2026-05-26 13:51:01 +00:00
Merge pull request #52 from lichess-org/explosionSquares
Explosion squares
This commit is contained in:
@@ -1,8 +1,3 @@
|
||||
/// Dart chess library for native platforms.
|
||||
///
|
||||
/// All classes are immutable except [PgnNode] and [PgnChildNode].
|
||||
library dartchess;
|
||||
|
||||
export 'src/constants.dart';
|
||||
export 'src/models.dart';
|
||||
export 'src/square_set.dart';
|
||||
|
||||
+1
-1
@@ -185,7 +185,7 @@ extension type const Rank._(int value) implements int {
|
||||
///
|
||||
/// The square is represented with an integer ranging from 0 to 63, using a
|
||||
/// little-endian rank-file mapping (LERF):
|
||||
/// ```
|
||||
/// ```txt
|
||||
/// 8 | 56 57 58 59 60 61 62 63
|
||||
/// 7 | 48 49 50 51 52 53 54 55
|
||||
/// 6 | 40 41 42 43 44 45 46 47
|
||||
|
||||
@@ -1318,6 +1318,24 @@ abstract class Atomic extends Position {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the set of squares that explode when [move] is played.
|
||||
///
|
||||
/// The explosion center ([move].to) and all surrounding non-pawn occupied
|
||||
/// squares are included. Returns an empty set if the move is not a capture.
|
||||
SquareSet explosionSquares(Move move) {
|
||||
if (move is! NormalMove) return SquareSet.empty;
|
||||
if (_getCastlingSide(move) != null) return SquareSet.empty;
|
||||
final capturedPiece = board.pieceAt(move.to);
|
||||
final isEnPassant =
|
||||
move.to == epSquare && board.pieceAt(move.from)?.role == Role.pawn;
|
||||
if (capturedPiece == null && !isEnPassant) return SquareSet.empty;
|
||||
final surrounding = kingAttacks(move.to)
|
||||
.intersect(board.occupied)
|
||||
.diff(board.pawns)
|
||||
.withoutSquare(move.from);
|
||||
return surrounding.withSquare(move.to);
|
||||
}
|
||||
|
||||
/// Plays a move without checking if the move is legal.
|
||||
///
|
||||
/// In addition to standard rules, all captures cause an explosion by which
|
||||
|
||||
@@ -773,6 +773,31 @@ void main() {
|
||||
expect(pos.hasInsufficientMaterial(Side.black), test[2]);
|
||||
}
|
||||
});
|
||||
|
||||
test('explosionSquares', () {
|
||||
// Giuoco Piano: Bxf7+ explodes f7 (center), f6 (knight), e8 (king), f8 (bishop)
|
||||
// g7 is a pawn and is not included
|
||||
final pos = Atomic.fromSetup(Setup.parseFen(
|
||||
'r1bqkb1r/pppp1ppp/2n2n2/4p3/2B1P3/5N2/PPPP1PPP/RNBQK2R w KQkq - 4 4'));
|
||||
expect(
|
||||
pos.explosionSquares(NormalMove.fromUci('c4f7')),
|
||||
SquareSet.fromSquares([Square.f7, Square.f6, Square.e8, Square.f8]),
|
||||
);
|
||||
|
||||
// Non-capture move returns empty set
|
||||
expect(
|
||||
pos.explosionSquares(NormalMove.fromUci('d2d3')),
|
||||
SquareSet.empty,
|
||||
);
|
||||
|
||||
// En passant: explosion centered on the destination square
|
||||
final epPos = Atomic.fromSetup(Setup.parseFen(
|
||||
'rnbqkbnr/ppp1p1pp/8/3pPp2/8/8/PPPP1PPP/RNBQKBNR w KQkq f6 0 3'));
|
||||
expect(
|
||||
epPos.explosionSquares(NormalMove.fromUci('e5f6')),
|
||||
const SquareSet.fromSquare(Square.f6),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('Antichess', () {
|
||||
|
||||
Reference in New Issue
Block a user