In this article, we are going to see how to extract data from PGN Files using the chess library in Python.
With the help of the chess library in python, we can perform several operations like validating a move, extracting data, and even making moves on the chessboard. In this article, we will extract data from a PGN file or a PGN string using the python-chess library.
Installing the library: Enter the following command in the command prompt.
pip install chess
What are PGN files?
PGN stands for Portable Game Notation. It is the standard format used to record the moves played by the players in a chess game. By using the PGN format, we can record and store the game moves in a regular text file.
Whenever we play chess online on popular websites like https://chess.com or https://lichess.org, these websites automatically generate the PGN files of our games. We can use these files to watch and analyze our games in the future. We will use these PGN files in order to extract data from our chess games using the chess library in Python.
Let us take a look at the contents of a PGN file in order to understand the contents of the file.
[Event "Live Chess"] [Site "Chess.com"] [Date "2021.08.05"] [Round "-"] [White "urvishmhjn"] [Black "yannickhs"] [Result "1-0"] [CurrentPosition "r1b1q1r1/p2nbk2/4pp1Q/1p1p3B/2pP3N/1PP1P3/P4PPP/R4RK1 b - -"] [Timezone "UTC"] [ECO "A45"] [UTCDate "2021.08.05"] [UTCTime "09:25:32"] [WhiteElo "1220"] [BlackElo "1140"] [TimeControl "900+10"] [Termination "urvishmhjn won by resignation"] 1. d4 Nf6 2. Bf4 e6 3. e3 d5 4. Bd3 c5 5. c3 c4 6. Be2 Nc6 7. Nf3 Be7 8. Nbd2 O-O 9. O-O Nh5 10. Be5 Nxe5 11. Nxe5 Nf6 12. b3 b5 13. Qc2 Nd7 14. Ndf3 f6 15. Ng4 h5 16. Nh6+ gxh6 17. Qg6+ Kh8 18. Qxh6+ Kg8 19. Qxh5 Qe8 20. Qg4+ Kf7 21. Nh4 Rg8 22. Qh5+ Kf8 23. Qh6+ Kf7 24. Bh5+ 1-0
In the above file, we can see that some of the text is written inside square brackets. These square brackets are called tag pairs. The content inside a tag pair gives us basic information about the game and the players playing it. For example, tag pairs tell us the username of each player, the date on which the game was played, the time format of the game, which player won the game, etc.
We can also see the text without square brackets. This text represents the moves played by each player. The numbers 1., 2., 3., etc. denote the move numbers. The text d4, Nf6, Bh+, etc. is the standard way of denoting the movement of a piece on the chessboard. Text 1-0 written at the end of the file denotes that white has won the game. 0-1 means that black has won, and 1/2-1/2 means that the game was a draw.
Implementation
Now that we understand what PGN files are, we will import the chess library and call the Board() function to create a virtual chessboard.
We will also need to import chess.pgn to perform operations on the pgn file/string.
Python3
import chess import chess.pgn # creating a virtual chessboard board = chess.Board() print (board) |
Output:
r n b q k b n r p p p p p p p p . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . P P P P P P P P R N B Q K B N R
If you have a .pgn file from which you want to extract data, use the following code. If you play chess on the above-mentioned websites, you can download the PGN files of your games from those websites.
pgn = open(“your-pgn-file.pgn”) # opening the file in python
game = chess.pgn.read_game(pgn) # reading the game present in file
If you have a string that contains the pgn file’s data, you will need to convert the string into a StringIO object because the chess library only supports the StringIO objects. You can use the following code.
Python3
# We need to convert the PGN string into a StringIO object # to use a string in python-chess from io import StringIO # Paste your PGN string here pgn_string = """[Event "Live Chess"] [Site "Chess.com"] [Date "2021.08.05"] [Round "-"] [White "urvishmhjn"] [Black "yannickhs"] [Result "1-0"] [CurrentPosition "r1b1q1r1/p2nbk2/4pp1Q/1p1p3B/2pP3N/1PP1P3/P4PPP/R4RK1 b - -"] [Timezone "UTC"] [ECO "A45"] [UTCDate "2021.08.05"] [UTCTime "09:25:32"] [WhiteElo "1220"] [BlackElo "1140"] [TimeControl "900+10"] [Termination "urvishmhjn won by resignation"] 1. d4 Nf6 2. Bf4 e6 3. e3 d5 4. Bd3 c5 5. c3 c4 6. Be2 Nc6 7. Nf3 Be7 8. Nbd2 O-O 9. O-O Nh5 10. Be5 Nxe5 11. Nxe5 Nf6 12. b3 b5 13. Qc2 Nd7 14. Ndf3 f6 15. Ng4 h5 16. Nh6+ gxh6 17. Qg6+ Kh8 18. Qxh6+ Kg8 19. Qxh5 Qe8 20. Qg4+ Kf7 21. Nh4 Rg8 22. Qh5+ Kf8 23. Qh6+ Kf7 24. Bh5+ 1-0 """ # Converting the string into StringIO object pgn = StringIO(pgn_string) # Reading the game game = chess.pgn.read_game(pgn) |
We have defined a variable called game. It contains information about the entire game.
Let’s now find out some of the details of the game.
Python3
# username of the player playing with white white_username = game.headers[ 'White' ] # username of the player playing with black black_username = game.headers[ 'Black' ] time_control = game.headers[ 'TimeControl' ] # time format of the game # who won the game game_result = game.headers[ 'Result' ] # Make sure that each header name # used above is present in the PGN print ( "White's chess.com Username:" , white_username) print ( "Black's chess.com Username:" , black_username) print ( "Game's Time Control:" , time_control, "seconds" ) print ( "Game Result:" , game_result) # If white wins: 1-0 # If black wins: 0-1 # If game drawn: 1/2-1/2 |
Output:
White's chess.com Username: urvishmhjn Black's chess.com Username: yannickhs Game's Time Control: 900+10 seconds Game Result: 1-0
We can get the FEN (FEN is a text notation used to display the position of each piece at any given moment in the game) at any position in the game with the following code.
Python3
# The move number for which we want the FEN move_number = 8 # Go through each move in the game until # we reach the required move number for number, move in enumerate (game.mainline_moves()): # It copies the move played by each # player on the virtual board board.push(move) # Remember that number starts from 0 if number = = move_number: break fen = board.fen() print (fen) |
Output:
r1bq1rk1/pp2bppp/4p3/3pn2n/2pP4/2P1PN2/PP1NBPPP/R2Q1RK1 w – – 0 11
If you want to visualize the chessboard, you can print the board on the terminal.
Python3
print (board) |
Output:
r n b q k b . r p p . . . p p p . . . . p n . . . . p p . . . . . . . P . B . . . . P B P . . . P P . . . P P P R N . Q K . N R
Note: If you want real visualization of the chessboard, instead of a printout on the terminal, use Jupyter Notebook. The output in Jupyter Notebook will be something like this.
Python3
display(board) |