Threefold repetition is missed after a double pawn push #432

Closed
opened 2026-10-15 22:24:02 +00:00 by root · 3 comments
root commented 2026-10-15 22:24:02 +00:00 (Migrated from gitlab.core-project.space)

What happens

A threefold repetition is missed whenever a double pawn push sits in the history. Every double push sets the en passant square (packages/engine/src/rules/search-board.ts:223-233), and the Zobrist key hashes its file whether or not a capture is possible (packages/engine/src/state/zobrist.ts:81-83). The position after the push never matches the same position reached later, so the count is off.

FIDE counts two positions as the same unless an en passant capture is actually available.

Reproduce

Game.fromUci("e2e4 e7e5 g1f3 b8c6 f3g1 c6b8 g1f3 b8c6 f3g1 c6b8").value.status();
// { kind: "ongoing" }, expected { kind: "draw", reason: "threefold" }

Game.fromUci("g1f3 b8c6 f3g1 c6b8 g1f3 b8c6 f3g1 c6b8").value.status();
// { kind: "draw", reason: "threefold" }

Done when

  • The en passant file enters the key only when a pawn of the side to move can legally capture en passant, in both zobristKey and updateZobristKey.
  • Both lines above reach a threefold draw, with a test for each, plus one where the en passant capture is legal and the positions must stay distinct.
## What happens A threefold repetition is missed whenever a double pawn push sits in the history. Every double push sets the en passant square (`packages/engine/src/rules/search-board.ts:223-233`), and the Zobrist key hashes its file whether or not a capture is possible (`packages/engine/src/state/zobrist.ts:81-83`). The position after the push never matches the same position reached later, so the count is off. FIDE counts two positions as the same unless an en passant capture is actually available. ## Reproduce ```ts Game.fromUci("e2e4 e7e5 g1f3 b8c6 f3g1 c6b8 g1f3 b8c6 f3g1 c6b8").value.status(); // { kind: "ongoing" }, expected { kind: "draw", reason: "threefold" } Game.fromUci("g1f3 b8c6 f3g1 c6b8 g1f3 b8c6 f3g1 c6b8").value.status(); // { kind: "draw", reason: "threefold" } ``` ## Done when - The en passant file enters the key only when a pawn of the side to move can legally capture en passant, in both `zobristKey` and `updateZobristKey`. - Both lines above reach a threefold draw, with a test for each, plus one where the en passant capture is legal and the positions must stay distinct.
root commented 2026-10-15 22:42:25 +00:00 (Migrated from gitlab.core-project.space)

mentioned in commit 8d34a3120b

mentioned in commit 8d34a3120b4111bcdcab3adc6f7221b98c0906b8
root commented 2026-10-15 22:42:33 +00:00 (Migrated from gitlab.core-project.space)

mentioned in merge request !547

mentioned in merge request !547
root commented 2026-10-15 23:37:12 +00:00 (Migrated from gitlab.core-project.space)

mentioned in commit 10f7ed9c73

mentioned in commit 10f7ed9c73bc75251d3adfdf763264db1eea9524
root (Migrated from gitlab.core-project.space) closed this issue 2026-10-15 23:47:39 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
amaurycoudr/chess-project#432
No description provided.