Skip to content

fix(chess): parse compact PGN move numbers (1.e4) on import - #946

Open
abdulwaarith0 wants to merge 1 commit into
OpenKnight-Foundation:mainfrom
abdulwaarith0:fix/pgn-compact-move-numbers
Open

fix(chess): parse compact PGN move numbers (1.e4) on import#946
abdulwaarith0 wants to merge 1 commit into
OpenKnight-Foundation:mainfrom
abdulwaarith0:fix/pgn-compact-move-numbers

Conversation

@abdulwaarith0

Copy link
Copy Markdown
Contributor

Summary

parse_moves() in backend/modules/chess/src/pgn.rs stripped move numbers with ^\d+\.+$, which only matches when the move number is its own whitespace-separated token (the spaced form 1. e4). A compact but valid PGN where the number is glued to the move (1.e4 e5 2.Nf3 Nc6, produced by many exporters/engines) tokenized to ["1.e4", "e5", "2.Nf3", "Nc6"]; the 1.e4/2.Nf3 tokens slipped through the filter and were rejected by the SAN parser.

This is live via the JWT-authenticated POST /games/import endpoint (backend/modules/api/src/games.rs:396), so importing a compact-format PGN returned a 422 "Illegal move" for a perfectly legal game.

Fix

Strip a leading move-number prefix from each token (^\d+\.+, no trailing $ anchor) instead of dropping whole-number-only tokens:

let move_number_prefix = Regex::new(r"^\d+\.+").unwrap();
...
.map(|token| move_number_prefix.replace(token, "").into_owned())
.filter(|token| !token.is_empty() && !result_regex.is_match(token))

This handles 1.e4, 1. e4, 1...e5, and 10.Ba2 uniformly.

Before / after

Input Before After
1.e4 e5 2.Nf3 Nc6 (compact) ["1.e4","e5","2.Nf3","Nc6"] → 422 ❌ ["e4","e5","Nf3","Nc6"] → ✅
1. e4 e5 2. Nf3 Nc6 (spaced) ["e4","e5","Nf3","Nc6"] unchanged ✅

Tests

Added regression tests for compact, black-continuation (1...e5), and two-digit move numbers. All 9 pgn tests pass (6 existing + 3 new).

Closes #945

parse_moves() stripped move numbers with ^\d+\.+$, which only matches
when the number is its own whitespace-separated token (1. e4). Compact
PGNs where the number is glued to the move (1.e4 e5 2.Nf3) tokenized to
["1.e4", "2.Nf3", ...], slipped through the filter, and were rejected
by the SAN parser — so POST /games/import returned a false 422 "Illegal
move" for legal games.

Strip a leading move-number prefix from each token (^\d+\.+, no trailing
anchor) instead of dropping whole-number-only tokens, handling 1.e4,
1. e4, 1...e5, and 10.Ba2 uniformly. Adds regression tests for compact,
black-continuation, and two-digit move numbers.

Closes OpenKnight-Foundation#945
@abdulwaarith0
abdulwaarith0 force-pushed the fix/pgn-compact-move-numbers branch from a678085 to c869f8e Compare August 15, 2026 10:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BE: PGN import rejects compact move-number format (1.e4) with a false "Illegal move"

1 participant