# What professional game has the quickest sequence, starting from move one, to quadrupled pawns?

In the blog "AJEDREZ, SIN DUDA", I came across a page that gives a game featuring quadrupled pawns.

``````[Title "Zheliandinov-T. Sereteli, 35th Championship of the USSR, Kharkov, 1967"]
[FEN "2r1kbr1/pp3pqp/5p2/3N1p2/5p2/6P1/PPn1BR1P/R2Q2K1 w - - 0 1"]
``````

It occurred to me that this game might have the shortest sequence, starting from move one in a professional chess game, to quadrupled pawns. It happens here in just 18 moves.

I have three points of focus.

1. Is this the shortest such game that satisfies my requirements?
2. I cannot find the score for the mentioned game. If you can find it, please link it and put it into the replayer.
3. Is there a way to easily find collections of quadrupled pawn games online?

I thought it would be interesting to try a variation of @Phonon's approach and treat the search as essentially a pattern-matching task using regular expressions. So, after performing the same expansion of a FEN and isolating the central six ranks, I passed the resulting string to the `search` function of Python's `re` package, looking for occurrences of pawn characters separated by any eight intervening characters (I haven't removed the rank separators from the expanded FEN):

``````# Look for games in the given file that
# have 4 adjacent pawns in a column.
def process_file(file):
file = open(file, encoding = "ISO-8859-1")

# Form the regular expressions for both colours.
white_pattern = "P........P........P........P"
black_pattern = "p........p........p........p"

while game:
board = game.board()
for move in game.mainline_moves():
board.push(move)
fen = board.fen()
# Expand the empty-square digits in the FEN to dots
# and extract just the board position.
pieces = "".join(["."*int(c) if c.isdigit() else c for c in fen])[:71]
# Drop first and last ranks as they can't contain pawns.
match_area = pieces[9:-9]
# Give up if neither side has sufficient pawns.
if match_area.count('P') < 4 and match_area.count('p') < 4:
break

if(re.search(white_pattern, match_area)):
print(game, "\n")
break

if(re.search(black_pattern, match_area)):
print(game, "\n")
break

``````

I have kept the logic as simple as possible for clarity but an obvious improvement would be to adapt it for different numbers of pawns by generating the pattern strings using string replication.

In practice, I found the matching to be relatively slow - around 100 games per second on my machine, which would take about 8 hours to search a 3,000,000 game database. I don't know whether that speed is limited by the python-chess library or the pattern matching.

As an alternative, I tried my own pgn-extract program which can accept regular expression FEN patterns to be matched when parsing games. For quadrupled pawns, there are only 24 possible configurations for each side, so these are relatively easy to enumerate (either by hand or programmatically); for instance:

``````FENPatternI "*/???????p/???????p/???????p/???????p/*/*/*"
FENPatternI "*/*/???????p/???????p/???????p/???????p/*/*"
FENPatternI "*/*/*/???????p/???????p/???????p/???????p/*"
``````

Using this approach, I was able to search a 3,200,000 game database in around 9 minutes, which is about 5,500 games per second. Interestingly, I found a slightly shorter version of something similar to the OP's original example, with the match after Black's 17th move:

``````[fen ""]
[Event "CSR-chT 9091"]
[Site "CSR"]
[Date "1991.01.19"]
[Round "5.2"]
[White "Novotny, Jiri"]
[Black "Obsivac, Josef"]
[Result "1-0"]

1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bg5 Bd7 7. Be2 Qa5
8. Bxf6 gxf6 9. Nb3 Qg5 10. g3 f5 11. Nd5 Rc8 12. f4 Qg7 13. e5 dxe5 14.
Nc5 Nd4 15. Nxd7 Nxc2+ 16. Kf2 exf4 17. N7f6+ exf6
{ 2r1kb1r/pp3pqp/5p2/3N1p2/5p2/6P1/PPn1BK1P/R2Q3R w k - 0 18 } 18. Bb5+ Kd8
19. Ne7+ 1-0

``````

• You are welcome. It is the ChessBase mega database from a few years ago. – kentdjb Apr 21 '19 at 13:44

1. Is there a way to easily find collections of quadrupled pawn games online?

No need to look online, you can do this on your own.

I've found 3 additional examples after parsing through roughly 300000 games of a TWIC DB:

1)

`````` [fen ""]
[Event "FSIM May"]
[Site "Budapest HUN"]
[Date "1996.05.13"]
[Round "11"]
[White "Lochte, T."]
[Black "Gross, S."]
[Result "0-1"]
[WhiteElo "2220"]
[BlackElo "2290"]
[PlyCount "54"]
[EventDate "1996.??.??"]
[SourceDate "2011.01.01"]
[StartPly "54"]

1. e4 c5 2. d4 cxd4 3. c3 dxc3 4. Nxc3 d6 5. Bc4 Nc6 6. Nf3 e6 7. O-O Bd7 8. Bf4 Qb8 9. Nb5 Ne5 10. Nxe5 dxe5 11. Bg3 Nf6 12. Qe2 a6 13. Nd4 Bd6 14. Rad1 Bc7 15. Nf3 Bc6 16. Bh4 h6 17. Bxf6 gxf6 18. Nh4 h5 19. Qf3 Bd8 20. Qg3 Qc7 21. Qg7 Rf8 22. f4 exf4 23. Rfe1 Qe5 24. Bd5 Qg5 25. Bxc6+ bxc6 26. Nf5 Bb6+ 27. Kh1 exf5 0-1
``````
`````` [fen ""]
[Event "8th World Seniors"]
[Site "Grieskirchen GER"]
[Date "1998.11.09"]
[Round "2"]
[White "Wegener, H."]
[Black "Knebel, W."]
[Result "0-1"]
[ECO "B95"]
[WhiteElo "2115"]
[PlyCount "54"]
[EventDate "1998.??.??"]
[SourceDate "2011.01.01"]
[StartPly "48"]

1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Bg5 e6 7. Bd3 Be7 8. O-O b5 9. a4 b4 10. Na2 a5 11. e5 dxe5 12. Bxf6 gxf6 13. Qf3 Ra7 14. Bb5+ Kf8 15. Nf5 exf5 16. Qe3 Qd4 17. Qh6+ Kg8 18. c3 Qg4 19. Qe3 Rc7 20. cxb4 axb4 21. Rfc1 Rxc1+ 22. Rxc1 Kg7 23. h3 Qg5 24. f4 exf4 25. Qxe7 Be6 26. h4 Qg3 27. b3 f3 0-1
``````
`````` [fen ""]
[Event "Open"]
[Site "Pula CRO"]
[Date "2001.05.24"]
[Round "7"]
[White "Molnar, Be"]
[Black "Polak, T."]
[Result "1-0"]
[ECO "D42"]
[WhiteElo "2352"]
[BlackElo "2503"]
[PlyCount "80"]
[EventDate "2001.05.18"]
[SourceDate "2011.01.01"]
[StartPly "66"]

1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 Nf6 5. Nc3 e6 6. Nf3 Be7 7. cxd5 Nxd5 8. Bd3 Nc6 9. O-O O-O 10. Re1 Bf6 11. Be4 Nce7 12. Qd3 h6 13. Ne5 Nxc3 14. Qxc3 Nf5 15. Be3 a5 16. Rad1 a4 17. Ng4 Bg5 18. Bxf5 exf5 19. Bxg5 hxg5 20. Ne5 Qa5 21. Qc4 Be6 22. d5 Rac8 23. b4 axb3 24. Qxb3 Rc5 25. Ng6 Rc3 26. Qxb7 Rc7 27. Qb1 fxg6 28. Rxe6 Kh7 29. d6 Rd7 30. Qb3 Rfd8 31. g4 Qc5 32. Qd5 Qxd5 33. Rxd5 fxg4 34. a4 Ra8 35. Re7 Rdd8 36. a5 Ra6 37. d7 Ra7 38. Kg2 Raa8 39. Rxg5 Ra7 40. Rd5 Raa8 1-0
``````

Briefly, how I've done it in Python and using python-chess to read the PGN DB:

I scan through each game of the DB mapping each position to its FEN, then I expand the FEN by replacing numbers with a corresponding amount of dashes '-'. In the FEN notation numbers in between the rank '/'-separated sections denote how many empty squares there are before a piece reached on a given row) so e.g., this FEN

``````'3r4/3PR1pk/r5p1/P2R2p1/6p1/8/5P1P/6K1'
``````

becomes:

``````'---r----/---PR-pk/r-----p-/P--R--p-/------p-/--------/-----P-P/------K-'
``````

which you can easily do as follows:

(after removing everything after the first space `fen=fen[0:fen.index(' ')]`)

``````def isinteger(s):
try:
int(s)
return True
except ValueError:
return False

for el in fen:
if isinteger(el):
fen = fen.replace(el,int(el)*'-')
``````

Then we know we want to find consecutive rows having pawns (of same color) on the same files, so if you split the FEN string according to the '/' separators into a list (`splitfen = fen.split('/')`), you have to match the pattern that letter 'p' (denoting black pawns in FEN, similarly, 'P' for white) occurs in 4 consecutive elements of the list and at the same position of the strings of size 8 (to ensure they're on same file) which you can go about in many different way:

``````#(the function that finds all consecutively matching patterns for t)
def checkpattern(sp,t):
start = [sp[0]]
for i in sp[1:]:
if any(all(t == c for c in b) for b in zip(*(start+[i]))):
start.append(i)
else:
if len(start) > 1:
yield start
start = [i]
return

splitfen = fen.split('/')

forblack = list(checkpattern(splitfen,'p'))
forwhite = list(checkpattern(splitfen,'P'))
total = forblack+forwhite
for el in total:
if len(el)==4: #(since we want quadrupled pawns)
res = True
break
``````

All such kinds of search queries across chess DB's can be easily performed with a bit of scripting around the FEN to spot the wanted patterns (be they pawn structures, number of pieces etc).

• This looks more stable than trying to figure when a player has quadrupled pawns based on the game score alone, which was what I might have tried to do. We could assign dictionary values black['a7'] = ... = black['h7'] = 1 at the start of each game, then parse each capture of or by a pawn. That would be an interesting exercise, but your way just makes more sens. – aschultz Apr 18 '19 at 23:55

I found the game in the chess365.com database. Here's the link.

Here is the search that I used to find it.

Here's the game in the replayer.

``````[FEN ""]
1.  e4  c5 2.   Nf3 Nc6 3.  d4  cxd4 4. Nxd4    Nf6 5.  Nc3 d6 6.   Bg5 Bd7 7.  Be2 Qa5 8.  Bxf6    gxf6 9. Nb3 Qg5 10. Nd5 Rc8 11. O-O Rg8 12. g3  f5 13.  f4  Qg7 14. e5  dxe5 15.    Nc5 Nd4 16. Nxd7    Nxc2 17.    Rf2 exf4 18.    N7f6+   exf6 19.    Bb5+    Kd8 20. Rxc2    fxg3 21.    Qd4 1-0
``````

I also found this collection of games with isolated triple pawns. Might be helpful.

Some google searching found a famous quadrupled pawn game played by the great Alekhine.

``````[fen ""]
1. d4 d5 2. Nf3 e6 3. e3 c6 4. Bd3 f5 5. Ne5 Qf6 6. Nd2 Nd7 7. f4 Nxe5 8. fxe5 Qf7 9. O-O Qc7 10. c4 Nh6 11. b3 Bd7 12. a4 Be7 13. cxd5 cxd5 14. Ba3 Bxa3 15. Rxa3 O-O 16. Ra2 Rac8 17. Qe2 Qb6 18. Rc2 Rxc2 19. Bxc2 Rc8 20. Bd3 Qb4 21. h3 Nf7 22. Rb1 Rc3 23. Kh2 a6 24. Qf1 Qa3 25. Rd1 Qb2 26. Qe2 Nd8 27. Rb1 Qa3 28. Rf1 Qb4 29. Bb1 b5 30. g4 bxa4 31. gxf5 Bb5 32. Nc4 Rxb3 33. fxe6 dxc4 34. Qf3 Rxb1 35. Rxb1 Qxb1 36. e7 Ne6 37. d5 Qg6 38. dxe6 Qe8 39. Qd5 h6 40. Qc5 c3 41. Qxc3 Qxe7 42. Qc8+ Qe8 43. Qc7 Qxe6 0-1
``````