Help with PGN to FEN strings with move list · Issue #1120 · niklasf/python-chess · GitHub
Skip to content

Help with PGN to FEN strings with move list #1120

Open

Description

@atenonai

I would like to achieve the following:

  1. Use a PGN-file as input.
  2. Output individual FEN strings for each position from a chosen perspective, including variations. The FEN position should be before the opposite color made their move.
  3. Include a move list after the FEN string (the first move would be the opposite color, and the second move would be the move from the chosen perspective).
  4. If any moves had annotations (comments/[%csl ...]/[%cal ...]) those should be preserved in the move list as well.

Example:

With the following PGN as input, and black as the chosen perspective…

[Event "?"]
[Site "?"]
[Date "????.??.??"]
[Round "?"]
[White "?"]
[Black "?"]
[Result "*"]

1. e4 c5 { Sicilian } { [%csl Gd4][%cal Gc5d4] } 2. Nf3 (2. Nc3 { Closed Sicilian } 2... d6) 2... d6 *

…the desired output would be:

[FEN "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"]
1. e4 c5 { Sicilian } { [%csl Gd4][%cal Gc5d4] }

[FEN "rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2"]
2. Nf3 d6

[FEN "rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2"]
2. Nc3 { Closed Sicilian } 2... d6

I hope that all made sense.

Is this possible? I would be grateful for any pointers on how to achieve it.

Activity

  1. atenonai commented on Nov 27, 2024

    @atenonai
    Author

    I figured out the first parts!

    How can I include not only moves but also the move numbers and comments/annotations from the PGN? If anyone could provide some pointers that would be great.

    import chess
    import chess.pgn
    
    pgn_file = '/path'
    repertoire_color = 'black'
    
    if repertoire_color == 'black':
        setup_positions = chess.WHITE  # FEN positions will be before opponents move
    elif repertoire_color == 'white':
        setup_positions = chess.BLACK  # FEN positions will be before opponents move
    
    with open(pgn_file) as pgn:
        parsed_pgn = chess.pgn.read_game(pgn)
    
    def extract_positions(node, color):
        if node.board().turn == color:
            fen = node.board().fen()
            
            if node.variations:
                # Get opponent move
                for variation in node.variations:
                    opponent_move = variation.move
                    # Convert move to algebraic notation
                    algebraic_opponent_move = node.board().san(opponent_move)
                    
                    if variation.variations:
                    # For each found move, check if there's a response in the repertoire
                        response_move = variation.variations[0].move
                        if response_move:
                        # Convert move to algebraic notation
                            algebraic_response_move = variation.board().san(response_move)
                            
                            # Print the position and move pair
                            print(f'[FEN "{fen}"]\n{algebraic_opponent_move} {algebraic_response_move}\n')
        
        # Recursively process nodes to extract all positions (both main line and sidelines)
        for variation in node.variations:
            extract_positions(variation, color)
    
    extract_positions(parsed_pgn, setup_positions)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions