Skip to content

Commit

Permalink
Scanner: fix parsing of PGNs w/ starting position
Browse files Browse the repository at this point in the history
PGNs can encode games starting from a specific position rather than
the normal starting position. Currently, Scanner will not parse these
correctly because it matches move lists only on lines beginning with
"1. ". This commit fixes this.
  • Loading branch information
mikeb26 committed May 29, 2023
1 parent 5a91e1f commit eeda81d
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 1 deletion.
55 changes: 55 additions & 0 deletions fixtures/pgns/0014.pgn
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
[Event "Fantasy Caro-Kann: Starting Position"]
[Result "*"]
[UTCDate "2023.05.29"]
[UTCTime "16:05:07"]
[Variant "Standard"]
[ECO "B12"]
[Opening "Caro-Kann Defense: Maróczy Variation"]

1. e4 c6 2. d4 d5 3. f3 *


[Event "Fantasy Caro-Kann: 3. ... dxe4"]
[Result "*"]
[UTCDate "2023.05.29"]
[UTCTime "16:05:48"]
[Variant "Standard"]
[FEN "rnbqkbnr/pp2pppp/2p5/3p4/3PP3/5P2/PPP3PP/RNBQKBNR b KQkq - 0 3"]
[SetUp "1"]

3... dxe4 4. fxe4 e5 5. Nf3 Bg4 (5... exd4 6. Bc4) 6. Bc4 Nd7 7. O-O Ngf6 8. c3 *


[Event "Fantasy Caro-Kann: 3. ... e6"]
[Result "*"]
[UTCDate "2023.05.29"]
[UTCTime "16:06:13"]
[Variant "Standard"]
[FEN "rnbqkbnr/pp2pppp/2p5/3p4/3PP3/5P2/PPP3PP/RNBQKBNR b KQkq - 0 3"]
[SetUp "1"]

3... e6 4. Nc3 Bb4 (4... Nf6 5. e5) 5. Bd2 Ne7 6. Bd3 *


[Event "Fantasy Caro-Kann: 3. ... g6"]
[Result "*"]
[UTCDate "2023.05.29"]
[UTCTime "16:06:42"]
[Variant "Standard"]
[FEN "rnbqkbnr/pp2pppp/2p5/3p4/3PP3/5P2/PPP3PP/RNBQKBNR b KQkq - 0 3"]
[SetUp "1"]

3... g6 4. Nc3 Bg7 5. Be3 *


[Event "Fantasy Caro-Kann: 3. ... Qb6"]
[Result "*"]
[UTCDate "2023.05.29"]
[UTCTime "16:07:08"]
[Variant "Standard"]
[FEN "rnbqkbnr/pp2pppp/2p5/3p4/3PP3/5P2/PPP3PP/RNBQKBNR b KQkq - 0 3"]
[SetUp "1"]

3... Qb6 4. Nc3 dxe4 5. fxe4 e5 6. Nf3 exd4 7. Nxd4 *


4 changes: 3 additions & 1 deletion pgn.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ const (
// a game or EOF was reached. Running scan populates
// data for Next() and Err().
func (s *Scanner) Scan() bool {
moveListRe := regexp.MustCompile(`^\d+\.`)

if s.err == io.EOF {
return false
}
Expand Down Expand Up @@ -64,7 +66,7 @@ func (s *Scanner) Scan() bool {
}
line := strings.TrimSpace(s.scanr.Text())
isTagPair := strings.HasPrefix(line, "[")
isMoveSeq := strings.HasPrefix(line, "1. ")
isMoveSeq := moveListRe.MatchString(line)
switch state {
case notInPGN:
if !isTagPair {
Expand Down
35 changes: 35 additions & 0 deletions pgn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,41 @@ func TestScanner(t *testing.T) {
}
}

func TestScannerWithFromPosFENs(t *testing.T) {
finalPositions := []string{
"rnbqkbnr/pp2pppp/2p5/3p4/3PP3/5P2/PPP3PP/RNBQKBNR b KQkq - 0 3",
"r2qkb1r/pp1n1ppp/2p2n2/4p3/2BPP1b1/2P2N2/PP4PP/RNBQ1RK1 b kq - 0 8",
"rnbqk2r/pp2nppp/2p1p3/3p4/1b1PP3/2NB1P2/PPPB2PP/R2QK1NR b KQkq - 5 6",
"rnbqk1nr/pp2ppbp/2p3p1/3p4/3PP3/2N1BP2/PPP3PP/R2QKBNR b KQkq - 3 5",
"rnb1kbnr/pp3ppp/1qp5/8/3NP3/2N5/PPP3PP/R1BQKB1R b KQkq - 0 7",
}
fname := "fixtures/pgns/0014.pgn"
f, err := os.Open(fname)
if err != nil {
panic(err)
}
defer f.Close()
scanner := NewScanner(f)
games := []*Game{}
for idx := 0; scanner.Scan(); {
game := scanner.Next()
if len(game.moves) == 0 {
continue
}
finalPos := game.Position().String()
if finalPos != finalPositions[idx] {
t.Fatalf(fname+" game %v expected final pos %v but got %v", idx,
finalPositions[idx], finalPos)
}
games = append(games, game)
idx++
}
if len(games) != len(finalPositions) {
t.Fatalf(fname+" expected %v games but got %v", len(finalPositions),
len(games))
}
}

func BenchmarkPGN(b *testing.B) {
pgn := mustParsePGN("fixtures/pgns/0001.pgn")
b.ResetTimer()
Expand Down

0 comments on commit eeda81d

Please sign in to comment.