1

I trying to extract move information and annotations from a few PGN files, outputting to a text file. My current code is:

import chess.pgn
import io
import os


def handle_san_error(pgn_file, game_str, san_error):
    # Skip the problematic move
    lines = game_str.splitlines()
    problematic_move = str(san_error).split()[2].strip("'")
    new_lines = [line for line in lines if problematic_move not in line]

    # Print the problematic move and file
    print(f"Error in file: {pgn_file}")
    print(f"Problematic move: {problematic_move}")

    return "\n".join(new_lines)

def process_pgn_files(pgn_files, output_file):
    with open(output_file, 'w') as out_file:
        first_game = True
        for pgn_file in pgn_files:
            print(f"Processing file: {pgn_file}")  # Print the current file being processed
            with open(pgn_file) as file:
                game_str = file.read()
                game_io = io.StringIO(game_str)

                while True:
                    try:
                        game_io.seek(0)
                        game = chess.pgn.read_game(game_io)
                        if game is None:
                            break
                    except chess.IllegalMoveError as e:
                        game_str = handle_san_error(pgn_file, game_str, e)  # Pass the pgn_file to the function
                        game_io = io.StringIO(game_str)
                        continue

                    node = game
                    error_in_game = False

                    while not node.is_end():
                        move = node.move

                        if move is None:
                            error_in_game = True
                            break

                        if not first_game:
                            out_file.write('===\n')
                        else:
                            first_game = False

                        out_file.write(str(move) + '\n')

                        if node.comment:
                            out_file.write(node.comment.strip() + '\n')

                        out_file.write('\n')

                        node = node.next()

                    if error_in_game:
                        break

pgn_directory = 'directory'
output_file = 'output.txt'

pgn_files = [os.path.join(pgn_directory, f) for f in os.listdir(pgn_directory) if f.endswith('.pgn')]

process_pgn_files(pgn_files, output_file)

I want the output to look like this:

1.d4 f5

The Dutch Defense

2.Nf3 e6 3.Nc3

Blocking his c-pawn, White aims for rapid development and the central break, e2-e4.

3...Nf6 4. Bg5 Be7 5. Bxf6

White exchanges in order to break with e2-e4. The inherent problem with the Dutch Defense is the early weakening of the kingside with 1...f5.

5...Bxf6 6. e4

White is missing his dark-squared Bishop. Recommended for Black is 6...d5, which forces White to clarify his intentions in the center.

6...fxe4

Not best, as it activates White's QN.


Any help would be greatly appreciated!

1 Answers1

1
def process_pgn_files(pgn_files, output_file):
    with open(output_file, 'w') as out_file:
        first_game = True
        for pgn_file in pgn_files:
            print(f"Processing file: {pgn_file}")  # Print the current file being processed
            with open(pgn_file) as file:
                game_str = file.read()
                game_io = io.StringIO(game_str)

                while True:
                    try:
                        game_io.seek(0)
                        game = chess.pgn.read_game(game_io)
                        if game is None:
                            break
                    except chess.IllegalMoveError as e:
                        game_str = handle_san_error(pgn_file, game_str, e)  # Pass the pgn_file to the function
                        game_io = io.StringIO(game_str)
                        continue

                    node = game
                    error_in_game = False
                    commentary = ""

                    while not node.is_end():
                        move = node.move

                        if move is None:
                            error_in_game = True
                            break

                        if not first_game:
                            out_file.write('===\n')
                        else:
                            first_game = False

                        out_file.write(str(move) + ' ')

                        if node.comment:
                            commentary += node.comment.strip() + ' '

                        node = node.next()

                    if commentary:
                        out_file.write('\n\n' + commentary.strip() + '\n\n')

                    if error_in_game:
                        break

Let's create new `commentary string to hold all the annotations for the current move. Inside the while loop append the current node's comment to the commentary string, separated by a space. After the loop check if there is any commentary and if so write it to the output file, separated by two newlines.

godot
  • 3,422
  • 6
  • 25
  • 42