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

object Dfen

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 Object
trait Matchable
class Any
Self type
Dfen.type
object LeaperAttacks

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 Object
trait Matchable
class Any
Self 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

  1. 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.
  2. 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 maxLen but is not recursed into (the game is over). All branches continue to be searched so that maxLen is 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 Object
trait Matchable
class Any
Self 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 Object
trait Matchable
class Any
Self type
object MoveGenerator

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 Object
trait Matchable
class Any
Self 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 Object
trait Matchable
class Any
Self type
object Perft

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 Object
trait Matchable
class Any
Self type
Perft.type