V3#123
Draft
CorentinGS wants to merge 93 commits into
Draft
Conversation
Introduce MoveTree as the first-class game tree owner for root/current cursor state, traversal, variation enumeration, cloning, and line splitting. Keep active move insertion routed through Game so legality checks, terminal guards, and outcome evaluation remain authoritative. Update PGN parsing/rendering, opening callers, tests, README, package docs, and migration notes for MoveTree access and the new move insertion return signatures.
Carve the 1279-line engine.go into:
movegen.go (309 lines) - move generation orchestration
calcMoves, unsafeMoves, status, hasLegalMove, hasStandardMove,
visitLegalMoves, visitStandardMoves, moveMatchesMode,
legalMoveContext + methods, standardMoves, movePool,
promoPieceTypes, maxPossibleMoves, moveGenerationMode
attacks.go (164 lines) - attack detection
isInCheck, isSquareAttackedBy, squaresAreAttacked,
pinnedRayForPiece, pawnCheckers, pawnAttacks,
sliderBitboards, squaresAligned
movetags.go (116 lines) - move tag computation
moveTags, moveTagsForMode, moveTagsForPiece,
requiresOwnKingCheckSimulation, moveFromAlignedWithOwnKing,
exposesOwnKingToSlider
castling.go (66 lines) - castling
hasCastleMove, castleMovesInto
magic.go (243 lines) - magic bitboards
diaAttack, slowDiaAttack, hvAttack, slowHVAttack,
initMagicAttack*, magicOccupancies, rookMagicMask,
bishopMagicMask, rookMagics, bishopMagics, attack tables
patterns.go (355 lines) - piece patterns, geometry, init orchestrator
bbForPossibleMoves, pawnMoves, geometry helpers
(rayStep, squaresBetween, squareFromBit, etc.),
static pattern tables (bbKnightMoves, bbKingMoves, ...),
sliding-attack tables and their init functions,
master init() orchestrating all table population
No public API change. The master init() lives in patterns.go and calls
the per-table init functions in patterns.go and magic.go. Files form
a clean DAG with no cycles:
movegen.go -> attacks.go -> patterns.go -> magic.go
-> movetags.go
-> castling.go -> attacks.go
-> patterns.go -> magic.go
Each new file passes go vet and go build independently because the
package boundary is unchanged. The split is individually reversible
(folding any single file back into engine.go would still compile).
Extract decodeSANText as the single SAN parse+resolve entry point, parameterised by canonical flag. MoveTextCodec.Decode now owns the canonical decision via policy; redundant validatePositionMove removed for SAN and long algebraic (resolveSANMove already guarantees legality). Replace parseMove's 180-line token-by-token SAN reconstruction with grammar-aware token collection that delegates to the codec. Delete dead helpers: isPromotionDestination, parsePieceType, parseSquare, and the now-unnecessary algebraicNotation.Decode wrapper. Net -120 lines. One locality for SAN grammar, leniency, legality, and diagnostics.
Board.update and Position.updateHash both read a shared moveEffect struct so the board mutation and the Zobrist hash delta cannot drift on en-passant squares, castle rook squares, or capture targets. Special-move effects (en-passant direction, castle rook rank) are derived from the moving piece's color rather than Position.turn, so unsafe moves through Game.UnsafeMove / Game.UnsafePushMoveText cannot apply effects for the wrong side; Board.update captures before shifting the mover's color aggregate so the same square can be cleared and re-added under the mover's color without leaving whiteSqs/blackSqs out of sync with the per-piece bitboards and mailbox. TestComputeMoveEffect pins the descriptor across quiet moves, captures, en-passant for both colors, all four castles, both promotions, and the degenerate empty-origin case. TestApplyMoveDifferential walks the perft positions in lockstep and asserts incremental hash equals full recompute at every node. TestUnsafeTransitionConsistency guards the three unsafe paths the consolidation could regress: out-of-turn black castling, out-of-turn en-passant tagging, and the unsafe king-on-friendly-square move. Renumber docs/adr/0001-zobrist-hash-consolidation.md to 0017 so each ADR has a unique sequence number.
Avoid decoding the constant starting FEN for every parsed Game. BenchmarkPGN_FullGameDecode_BigBig on linux/amd64, Ryzen 9 5950X: time -20.50%, bytes -0.78%, allocations -0.41%, throughput +25.78%.
Resolve ordinary pawn pushes from destination-directed candidates instead of falling back to full legal-move enumeration. BenchmarkPGN_FullGameDecode_BigBig on linux/amd64, Ryzen 9 5950X: time -35.57%, bytes -0.35%, allocations -1.60%, throughput +55.24%.
Return one-character move token values as slices of the lexer input instead of allocating strings. BenchmarkPGN_FullGameDecode_BigBig on linux/amd64, Ryzen 9 5950X: time -1.37%, bytes -1.56%, allocations -32.70%, throughput +1.40%.
Return tag values as lexer input slices unless escape decoding requires a builder. Benchmarks on linux/amd64, Ryzen 9 5950X: BenchmarkPGNRecord_Tags_Big: time -7.07%, bytes -3.69%, allocations -79.00%. BenchmarkPGN_FullGameDecode_BigBig: time -5.40%, bytes -0.75%, allocations -7.83%.
Build FEN strings directly into byte buffers, add allocation-free move continuation iteration, and simplify PGN parser checks and error formatting. BenchmarkPGN_FullGameDecode_BigBig on linux/amd64, Ryzen 9 5950X: no significant time or throughput change (p=0.684); allocations unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.