pgn2 1.2.0 → 1.2.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +29 -0
- data/lib/pgn/move_calculator.rb +30 -14
- data/lib/pgn/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 963f48df8fbfe5d69097030a9434a05b82e211c235772273f03bd11178afb8a5
|
|
4
|
+
data.tar.gz: 6bc38e0387e7061e3649fe52d22e5f01dabdc7029f8c27294d56b62a3779a76c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e81b88377f5d1ab6102a5b15d4d006feb4201647125b5b3d434b826dfa55cac60c82048fc8d4d2a4c8aa7d1600d6ba4edd472f27d063d258703d8e225c0832cc
|
|
7
|
+
data.tar.gz: 06cb00152b81f2124749fbc743356a25a7ee44e049c7779fb397660a84ebfefee8afcf4679f86ac633ff12b771db007123308cd5c65520ae8329e7334b340ab9
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.2.1 (2026-08-13)
|
|
4
|
+
|
|
5
|
+
### Summary
|
|
6
|
+
|
|
7
|
+
Replay (move-application) throughput quick win on the `MoveCalculator`
|
|
8
|
+
hot path. No public API changes; serialized PGN/FEN output stays
|
|
9
|
+
byte-identical. See `bench/IMPROVEMENTS.md` for the per-step deltas.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
- **`MoveCalculator#valid_square?`**: integer compares (`file >= 0 &&
|
|
13
|
+
file < 8`) instead of `(0..7).include?(file)`, which both allocates a
|
|
14
|
+
`Range` per call and is ~3.4x slower. This predicate sits inside the
|
|
15
|
+
`first_piece` / `move_origins` / `king_position` inner board-scanning
|
|
16
|
+
loops — the dominant replay compute site (~46% of replay CPU via
|
|
17
|
+
per-method timing, not the SAN regex parse as had been assumed).
|
|
18
|
+
- **`MoveCalculator#compute_origin`**: string `case` (`when 'B','R','Q',...`)
|
|
19
|
+
instead of `/[brq]/i` regex `===` matches, removing 4 `MatchData`
|
|
20
|
+
allocations per move.
|
|
21
|
+
- **`MoveCalculator#first_piece`**: returns only the `[file, rank]` square
|
|
22
|
+
(`nil` when the scan runs off the edge) instead of a `[piece, square]`
|
|
23
|
+
wrapper tuple; callers read the piece via a new `piece_at` helper. Removes
|
|
24
|
+
one array allocation per direction scan.
|
|
25
|
+
- Performance vs 1.2.0 (immortal game, 45 plies, fresh process each):
|
|
26
|
+
replay throughput 814.65 us/i -> 752.54 us/i (+8.2%); replay allocations
|
|
27
|
+
1709 -> 1571 objects (-138, -8.1%) and 103720 -> 92440 bytes (-10.9%).
|
|
28
|
+
182 specs pass; byte-identical FEN/PGN output; zero new rubocop offenses
|
|
29
|
+
vs 1.2.0. The piece-location-index rewrite (the real ~46% ceiling,
|
|
30
|
+
deferred "Approach B") is unchanged.
|
|
31
|
+
|
|
3
32
|
## 1.2.0 (2026-08-13)
|
|
4
33
|
|
|
5
34
|
### Summary
|
data/lib/pgn/move_calculator.rb
CHANGED
|
@@ -185,9 +185,9 @@ module PGN
|
|
|
185
185
|
return nil if move.castle
|
|
186
186
|
|
|
187
187
|
possibilities = case move.piece
|
|
188
|
-
when
|
|
189
|
-
when
|
|
190
|
-
when
|
|
188
|
+
when 'B', 'R', 'Q', 'b', 'r', 'q' then direction_origins
|
|
189
|
+
when 'K', 'N', 'k', 'n' then move_origins
|
|
190
|
+
when 'P', 'p' then pawn_origins
|
|
191
191
|
else # don't care move, used in variations
|
|
192
192
|
return nil
|
|
193
193
|
end
|
|
@@ -207,8 +207,8 @@ module PGN
|
|
|
207
207
|
possibilities = []
|
|
208
208
|
|
|
209
209
|
directions.each do |dir|
|
|
210
|
-
|
|
211
|
-
possibilities << square if
|
|
210
|
+
square = first_piece(destination_coords, dir)
|
|
211
|
+
possibilities << square if piece_at(square) == move.piece
|
|
212
212
|
end
|
|
213
213
|
|
|
214
214
|
possibilities
|
|
@@ -285,28 +285,44 @@ module PGN
|
|
|
285
285
|
attacking_piece = attacking_piece.upcase if move.black?
|
|
286
286
|
|
|
287
287
|
directions.each do |dir|
|
|
288
|
-
|
|
289
|
-
next unless
|
|
288
|
+
square = first_piece(king_pos, dir)
|
|
289
|
+
next unless piece_at(square) == move.piece && possibilities.include?(square)
|
|
290
290
|
|
|
291
|
-
|
|
292
|
-
possibilities.reject! { |p| p == square } if
|
|
291
|
+
next_square = first_piece(square, dir)
|
|
292
|
+
possibilities.reject! { |p| p == square } if piece_at(next_square) == attacking_piece
|
|
293
293
|
end
|
|
294
294
|
end
|
|
295
295
|
|
|
296
296
|
possibilities
|
|
297
297
|
end
|
|
298
298
|
|
|
299
|
+
# Walks from `from` in `direction` until it reaches the edge of the board
|
|
300
|
+
# or the first occupied square. Returns that square's `[file, rank]`
|
|
301
|
+
# coordinates, or `nil` if no piece was encountered before the edge. The
|
|
302
|
+
# caller reads the piece off the board itself, so this avoids allocating
|
|
303
|
+
# the `[piece, square]` wrapper tuple per direction scan.
|
|
304
|
+
#
|
|
299
305
|
def first_piece(from, direction)
|
|
300
306
|
file, rank = from
|
|
301
307
|
i, j = direction
|
|
302
308
|
|
|
303
|
-
|
|
309
|
+
loop do
|
|
310
|
+
file += i
|
|
311
|
+
rank += j
|
|
312
|
+
return nil if file.negative? || file > 7 || rank.negative? || rank > 7
|
|
304
313
|
|
|
305
|
-
|
|
306
|
-
|
|
314
|
+
square = [file, rank]
|
|
315
|
+
return square if board.at(file, rank)
|
|
307
316
|
end
|
|
317
|
+
end
|
|
308
318
|
|
|
309
|
-
|
|
319
|
+
# Reads the piece on a square, tolerating a nil square (returned by
|
|
320
|
+
# {#first_piece} when the scan ran off the edge). Kept as a helper so the
|
|
321
|
+
# callers read the piece once instead of unpacking a `[piece, square]`
|
|
322
|
+
# tuple per direction scan.
|
|
323
|
+
#
|
|
324
|
+
def piece_at(square)
|
|
325
|
+
square && board.at(square[0], square[1])
|
|
310
326
|
end
|
|
311
327
|
|
|
312
328
|
# If the move is a capture and there is no piece on the
|
|
@@ -331,7 +347,7 @@ module PGN
|
|
|
331
347
|
end
|
|
332
348
|
|
|
333
349
|
def valid_square?(file, rank)
|
|
334
|
-
|
|
350
|
+
file >= 0 && file < 8 && rank >= 0 && rank < 8
|
|
335
351
|
end
|
|
336
352
|
|
|
337
353
|
def destination_coords
|
data/lib/pgn/version.rb
CHANGED