dicechess.engine.movegen
Move generation for the Dice Chess Engine.
This package implements a fully bitboard-based pseudo-legal move generator. Each subsystem is responsible for a specific piece class, and MoveGenerator orchestrates them into a unified interface.
Architecture
| Object | Responsibility |
|---|---|
| PawnGeneration | Parallel push/capture generation via bitboard shifts |
| LeaperAttacks | Precomputed attack tables for Knights and Kings |
| MagicBitboards | O(1) sliding-piece attacks via magic-number hashing |
| MoveGenerator | Unified entry point; serialises bitboards into Move lists |
Move representation
All generated moves are 16-bit dicechess.engine.domain.Move values encoding origin square, destination square, and a 4-bit flag field (quiet, capture, castling, en passant, promotion).
Pseudo-legal generation
The generator produces pseudo-legal moves — moves that obey piece movement rules and match the available dice pool. Dice Chess has no notion of check: the game ends by direct King capture, so no check-based legality filtering exists anywhere in the engine. The only further constraint is the Maximum Micro-moves Rule, applied by LegalMovesFilter.
Attributes
Members list
Type members
Classlikes
Canonical DFEN normalization, shared with the dicechess-analytics position store.
Canonical DFEN normalization, shared with the dicechess-analytics position store.
The position dedup key (normalized_fen in analytics) and the opening-book key (OpeningBook.key) are the first four DFEN fields. Raw dicechess.engine.domain.FenParser.serialize writes an en-passant target after every pawn double-push, even when no capture is possible. In Dice Chess a turn spans several micro-moves, so the en-passant field at turn end is path-dependent: the same tactically-identical position serializes under many en-passant variants (target set vs cleared), which fragments the position store and the opening-book / equity samples.
normalizedFen removes that ambiguity with the X-FEN convention: an en-passant target is kept only when the side to move can actually capture it. Whether a capture exists is a move-generation property, so this lives next to PawnGeneration rather than in the pure-domain dicechess.engine.domain.FenParser (which must stay free of move-generation knowledge, and whose serialize/parse round-trip must remain intact).
The four-field result is, by contract, byte-for-byte the analytics normalized_fen. Any change here is a cross-repository breaking change and must be mirrored in the analytics normalizer and its round-trip test.
Attributes
- Source
- Dfen.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
Dfen.type
Precomputed attack tables for leaping pieces (Knights and Kings).
Precomputed attack tables for leaping pieces (Knights and Kings).
Since leapers are not blocked by other pieces, their attacks can be completely pre-calculated at JVM startup for all 64 squares.
Attributes
- Source
- LeaperAttacks.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
LeaperAttacks.type
Legal moves filter for Dice Chess.
Legal moves filter for Dice Chess.
Implements the Maximum Micro-moves Rule: a player must choose a first move that is part of the longest possible sequence of micro-moves achievable with the rolled dice.
Two types of legal first moves
- King-Capture — any sequence of micro-moves that ends with capturing the opponent's King is always legal, regardless of whether it is 1, 2, or 3 moves long.
- Non-King-Capture — any sequence of micro-moves that does not end with a King capture must achieve the globally optimal length
L*(state, dice).
Rules encoded here
- Normal move — consumes exactly one die of the matching piece type.
- Castling — requires and consumes both the King die (
6) and the Rook die (4) simultaneously. - King-Capture — terminates the game; a King capture contributes its depth to
maxLenbut is not recursed into (the game is over). All branches continue to be searched so thatmaxLenis computed correctly. - Active-color invariance — the active color is kept fixed for every intermediate state produced during a turn; it is not toggled between micro-moves.
Attributes
- Source
- LegalMovesFilter.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
LegalMovesFilter.type
Magic Bitboards implementation for sliding pieces (Bishops, Rooks, and Queens).
Magic Bitboards implementation for sliding pieces (Bishops, Rooks, and Queens).
Magic Bitboards provide O(1) attack-set lookup for blocking sliding pieces by encoding the current board occupancy into an index via a precomputed magic number multiplier:
index = ((occupancy & relevantMask) * magic) >>> (64 - relevantBits)
attack = table[offset + index]
When the object is first used, BishopTable (5248 entries) and RookTable (102400 entries) are populated for all 64 squares from the slow bishopAttacksClassic / rookAttacksClassic functions, run once per blocker subset of each line through a square rather than once per entry (see fillSlice). All subsequent attack lookups use the fast O(1) hash path.
The magic constants are a well-known standard set compatible with most chess engine implementations.
Attributes
- Source
- MagicBitboards.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
MagicBitboards.type
Unified move generator for Dice Chess. Coordinates between specialized generators for pawns, leapers, and sliding pieces.
Unified move generator for Dice Chess. Coordinates between specialized generators for pawns, leapers, and sliding pieces.
Attributes
- Source
- MoveGenerator.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
MoveGenerator.type
Highly optimized pawn move generation using Bitboard arithmetic.
Highly optimized pawn move generation using Bitboard arithmetic.
Unlike leaping pieces which are generated per-square, pawn pushes and attacks can be calculated in parallel for all pawns of a given color simultaneously using bitwise shifts.
Attributes
- Source
- PawnGeneration.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
PawnGeneration.type
Performance and correctness testing utility (Perft) for move generation and game-state transitions.
Performance and correctness testing utility (Perft) for move generation and game-state transitions.
Recursively counts the number of leaf nodes at a given depth. If state.dicePool is empty, MoveGenerator.generateAllMoves is used (standard chess pseudo-legal moves); otherwise, MoveGenerator.generateMoves generates moves constrained by the current dice roll.
Attributes
- Source
- Perft.scala
- Supertypes
-
class Objecttrait Matchableclass Any
- Self type
-
Perft.type