pgn2 1.4.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +34 -3
  3. data/.github/workflows/native.yml +32 -0
  4. data/.github/workflows/publish.yml +44 -2
  5. data/.github/workflows/release-gems.yml +40 -0
  6. data/.github/workflows/release.yml +52 -5
  7. data/.gitignore +9 -1
  8. data/.rubocop.yml +46 -6
  9. data/CHANGELOG.md +183 -1
  10. data/Gemfile +3 -0
  11. data/NOTICE.md +21 -0
  12. data/README.md +107 -5
  13. data/Rakefile +35 -10
  14. data/TODO.md +102 -31
  15. data/bench/baseline_moves.txt +38 -4
  16. data/bench/baseline_parse.txt +4 -4
  17. data/bench/cross_check.rb +61 -0
  18. data/bench/legal_moves.rb +38 -0
  19. data/bench/perft.rb +32 -0
  20. data/bench/profile_moves.rb +93 -0
  21. data/docs/superpowers/plans/2026-08-13-attack-masks-plan.md +51 -0
  22. data/docs/superpowers/plans/2026-08-13-perf-internals-plan.md +883 -0
  23. data/docs/superpowers/plans/2026-08-13-rust-bitboard-perft-plan.md +2442 -0
  24. data/docs/superpowers/plans/2026-08-14-chessie-migration.md +722 -0
  25. data/docs/superpowers/plans/2026-08-14-rust-integration-plan.md +444 -0
  26. data/docs/superpowers/specs/2026-08-13-attack-masks-design.md +57 -0
  27. data/docs/superpowers/specs/2026-08-13-perf-internals-design.md +111 -0
  28. data/docs/superpowers/specs/2026-08-13-rust-bitboard-perft-design.md +270 -0
  29. data/docs/superpowers/specs/2026-08-14-rust-integration-design.md +217 -0
  30. data/ext/pgn2_native/Cargo.lock +321 -0
  31. data/ext/pgn2_native/Cargo.toml +19 -0
  32. data/ext/pgn2_native/extconf.rb +8 -0
  33. data/ext/pgn2_native/pgn2-bitboard/Cargo.toml +10 -0
  34. data/ext/pgn2_native/pgn2-bitboard/src/board.rs +32 -0
  35. data/ext/pgn2_native/pgn2-bitboard/src/lib.rs +12 -0
  36. data/ext/pgn2_native/pgn2-bitboard/src/moves.rs +121 -0
  37. data/ext/pgn2_native/pgn2-bitboard/src/perft.rs +81 -0
  38. data/ext/pgn2_native/pgn2_native/Cargo.toml +11 -0
  39. data/ext/pgn2_native/pgn2_native/src/lib.rs +54 -0
  40. data/lib/pgn/bitboard.rb +13 -0
  41. data/lib/pgn/board.rb +103 -10
  42. data/lib/pgn/fen.rb +35 -46
  43. data/lib/pgn/game.rb +22 -13
  44. data/lib/pgn/lexer.rb +9 -6
  45. data/lib/pgn/move.rb +19 -15
  46. data/lib/pgn/move_calculator.rb +46 -20
  47. data/lib/pgn/notation.rb +24 -29
  48. data/lib/pgn/position.rb +60 -19
  49. data/lib/pgn/serializer.rb +13 -18
  50. data/lib/pgn/version.rb +1 -1
  51. data/lib/pgn/zobrist.rb +53 -0
  52. data/lib/pgn.rb +2 -0
  53. data/pgn2.gemspec +17 -10
  54. data/spec/bitboard_spec.rb +54 -0
  55. data/spec/board_spec.rb +53 -0
  56. data/spec/fen_spec.rb +65 -65
  57. data/spec/game_spec.rb +52 -15
  58. data/spec/lexer_spec.rb +5 -5
  59. data/spec/notation_spec.rb +5 -0
  60. data/spec/parser_spec.rb +8 -1
  61. data/spec/position_spec.rb +128 -27
  62. data/spec/serializer_spec.rb +4 -4
  63. data/spec/zobrist_spec.rb +46 -0
  64. metadata +101 -36
@@ -0,0 +1,51 @@
1
+ # Attack Masks + Retention Benchmark — Plan
2
+
3
+ TDD, inline execution. Commit per task. Honest benchmark reporting.
4
+
5
+ ## Task 1 — `PGN::Board` attack-mask tables (TDD)
6
+
7
+ Add `KNIGHT_ATTACKS` / `KING_ATTACKS` frozen 128-entry Arrays to `Board`,
8
+ entry `idx` = frozen `Array` of on-board 0x88 targets from `idx`. Build
9
+ from `Notation::KNIGHT_OFFS`/`KING_OFFS`, filtering `(t & 0x88).zero?`.
10
+
11
+ Spec (`spec/board_spec.rb`): mask entries equal the on-board squares the
12
+ offsets reach; corner squares have 2 knight / 3 king targets; centre e4
13
+ (0x54) has 8 knight / 8 king. E.g. `KNIGHT_ATTACKS[0] == [33, 18]`,
14
+ `KING_ATTACKS[0] == [1, 16, 17]`, `KNIGHT_ATTACKS[0x54].length == 8`.
15
+
16
+ ## Task 2 — `Notation` uses the masks
17
+
18
+ `reaches?` N/K → `Board::KNIGHT_ATTACKS[from].include?(to)` /
19
+ `KING_ATTACKS`. `knight_attacked?`/`king_attacked?` → iterate the mask.
20
+ `leaper_moves?` N/K → iterate the mask (pass mask instead of `OFFS`).
21
+
22
+ Spec: existing `notation_spec` + round-trip stay green (byte-identical
23
+ SAN). Add a focused test: a knight on e4 reaches d6/f6/etc.; a king on e1
24
+ reaches d1/d2/e2/f2/f1.
25
+
26
+ ## Task 3 — `MoveCalculator` K/N origins via the mask
27
+
28
+ Add `leaper_origins(mask)` iterating pre-filtered on-board targets;
29
+ `compute_origin` K/N branch calls
30
+ `leaper_origins(Board::KNIGHT_ATTACKS[dest_idx] ...)`; pawn path keeps
31
+ `move_origins(offsets)`.
32
+
33
+ Spec: existing `move_calculator_spec` + full round-trip stay green.
34
+
35
+ ## Task 4 — SAN-generation benchmark section
36
+
37
+ Add `bench/profile_moves.rb` section 8: reconstruct `Notation.san` for
38
+ every move of the immortal game from coordinate from/to (precomputed
39
+ once), allocation + throughput. Regenerate baseline; report whether the
40
+ mask change moved the SAN and replay (section 1/4) needles.
41
+
42
+ ## Task 5 — Retained-memory benchmark section
43
+
44
+ Add section 9: `MemoryProfiler` **retained** objects/memsize for
45
+ last-position-only, lazy (`each_position`) vs eager (`positions`). Fresh
46
+ `PGN::Game` per path. Regenerate baseline.
47
+
48
+ ## Task 6 — Final verification + CHANGELOG/README
49
+
50
+ Full suite, RuboCop (no new offenses on touched files), `rake bench`,
51
+ CHANGELOG + README update.