Background
PinDetector has two detection paths:
- Absolute pins — ray-cast from the king outward; finds one friendly piece followed by a compatible enemy sliding piece.
- Relative pins — scan every enemy sliding piece, look for two aligned friendly pieces where the second (anchor) is more valuable (
anchor > pinned && anchor >= 4).
Deduplication removes entries with the same (attacker, target) pair, and relative pins where the anchor is the king (anchor != 6) are excluded to avoid double-counting absolute pins.
Suspected issues
The King's Gambit test game (_prior vs zapblast, 54 moves) is used in both FullMotifDetectorTest and MotifE2ETest. The pin test in FullMotifDetectorTest uses contains (not containsExactly), intentionally leaving room for additional occurrences that haven't been audited:
assertThat(pins)
.extracting(GameFeatures.MotifOccurrence::moveNumber, GameFeatures.MotifOccurrence::side)
.contains(tuple(4, "white"), tuple(30, "black"), tuple(31, "black"),
tuple(38, "black"), tuple(50, "black"), tuple(51, "black"));
The unresolved questions are:
1. False positives from relative pin detection
The relative-pin scan may fire on positions where a sliding piece threatens two friendly pieces in a line but no real tactical pin exists (e.g. because the "pinned" piece is free to move without material loss). The condition anchor >= 4 (rook or queen) admits many alignments that aren't practically significant pins.
Specifically suspect:
- Endgame queen-and-rook positions (moves 29–54) where pieces shuffle along ranks/files and the relative-pin scan hits transient alignments.
- The anchor-value threshold: a pawn pinned in front of a rook by an enemy bishop may or may not be a meaningful pin depending on game phase.
2. Deduplication gap between absolute and relative paths
deduplicatePins removes entries with matching (attacker, target). But an absolute pin and a relative pin involving the same attacker and a different second friendly piece as anchor could both fire without being deduplicated.
3. Pins detected in positions where the piece has already "left" the pin square
PinDetector runs against every PositionContext in the game — one per half-move. A pin created on move N may be re-reported on moves N+1, N+2, … as long as the geometry holds. This is expected, but if the pinned piece moves and the geometry is transiently re-formed by a different piece, it could produce a spurious occurrence.
Suggested investigation steps
- Add a
FullMotifDetectorTest assertion using containsExactly (or at least record the full set) to enumerate every detected pin occurrence across all 108 half-moves and audit each one manually.
- For each suspicious occurrence, extract the FEN and add a targeted
PinDetectorTest unit test that asserts the expected count and (attacker, target, pinType).
- Consider tightening the relative-pin condition (e.g. requiring the pinned piece to be a knight or bishop, not just any piece cheaper than the anchor) or adding a move-significance heuristic.
- Consider whether
deduplicatePins should also deduplicate by target square (regardless of attacker) to prevent the same piece from being reported as pinned by two different attackers in the same position.
Acceptance criteria
FullMotifDetectorTest has a containsExactly assertion (or equivalent exhaustive list) for all expected pin occurrences in the King's Gambit game.
- Any false positives found are fixed and covered by new
PinDetectorTest FEN-based unit tests.
- Any false negatives found are fixed and similarly covered.
Background
PinDetectorhas two detection paths:anchor > pinned && anchor >= 4).Deduplication removes entries with the same
(attacker, target)pair, and relative pins where the anchor is the king (anchor != 6) are excluded to avoid double-counting absolute pins.Suspected issues
The King's Gambit test game (
_prior vs zapblast, 54 moves) is used in bothFullMotifDetectorTestandMotifE2ETest. The pin test inFullMotifDetectorTestusescontains(notcontainsExactly), intentionally leaving room for additional occurrences that haven't been audited:The unresolved questions are:
1. False positives from relative pin detection
The relative-pin scan may fire on positions where a sliding piece threatens two friendly pieces in a line but no real tactical pin exists (e.g. because the "pinned" piece is free to move without material loss). The condition
anchor >= 4(rook or queen) admits many alignments that aren't practically significant pins.Specifically suspect:
2. Deduplication gap between absolute and relative paths
deduplicatePinsremoves entries with matching(attacker, target). But an absolute pin and a relative pin involving the same attacker and a different second friendly piece as anchor could both fire without being deduplicated.3. Pins detected in positions where the piece has already "left" the pin square
PinDetector runs against every
PositionContextin the game — one per half-move. A pin created on move N may be re-reported on moves N+1, N+2, … as long as the geometry holds. This is expected, but if the pinned piece moves and the geometry is transiently re-formed by a different piece, it could produce a spurious occurrence.Suggested investigation steps
FullMotifDetectorTestassertion usingcontainsExactly(or at least record the full set) to enumerate every detected pin occurrence across all 108 half-moves and audit each one manually.PinDetectorTestunit test that asserts the expected count and(attacker, target, pinType).deduplicatePinsshould also deduplicate bytargetsquare (regardless of attacker) to prevent the same piece from being reported as pinned by two different attackers in the same position.Acceptance criteria
FullMotifDetectorTesthas acontainsExactlyassertion (or equivalent exhaustive list) for all expected pin occurrences in the King's Gambit game.PinDetectorTestFEN-based unit tests.