Answers.Body: <p>I'm confused by this statement:</p>
  <blockquote>
  <p>I need to feed my chess applications moves like e2-e4.</p>
  </blockquote>
  <p>Why? Computers that can read pgn files will understand the moves as they are formated.</p>
  <p>If you're inputting them manually, the notation works fine too. People play entire games blindfolded on the same notation. As the you go down the list of moves, the next move is played based on the state of the board from the previous move. That is how algebraic lines have always worked.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-03-04T19:45:54.877Z
Answers.LastActivityDate: 2022-03-04T19:45:54.877Z
Answers.UserDisplayName: tahabsim
Answers.Body: <p>PGN files are intended to be read and used by computer programs, not humans.  So, yes, the only way to do what you're asking is to brute-force search to make sure there's only one piece that can reach the destination square.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-03-03T21:04:32.293Z
Answers.LastActivityDate: 2022-03-03T21:04:32.293Z
Answers.UserDisplayName: patbarron
Answers.Body: <p>You can use a <a href="https://python-chess.readthedocs.io/en/latest/" rel="nofollow noreferrer">python chess library</a> to parse the moves of a game in a pgn file.</p>
  <p><strong>Code</strong></p>
  <pre><code>&quot;&quot;&quot;
  pip install chess
  &quot;&quot;&quot;
  
  import chess.pgn
  
  def parse_pgn(inpgn):
      with open(inpgn, encoding='utf-8') as h:
          while True:
              game = chess.pgn.read_game(h)
              if game is None:
                  break
  
              for node in game.mainline():
                  move = node.move 
                  pnode = node.parent
                  board = pnode.board()
  
                  move_from_sq = move.from_square
                  move_to_sq = move.to_square
  
                  print(board)
                  print(board.fen())
                  print(f'move: {move}')
                  print(f'move_from: {move_from_sq}')
                  print(f'move_from_name: {chess.SQUARE_NAMES[move_from_sq]}')
                  print(f'move_to: {move_to_sq}')
                  print(f'move_to_name: {chess.SQUARE_NAMES[move_to_sq]}')
                  print(f'{chess.SQUARE_NAMES[move_from_sq]}-{chess.SQUARE_NAMES[move_to_sq]}')
                  print(f'piece: {board.piece_at(move.from_square).symbol()}')
                  print()
  
  def main():
      inpgn = 'sample.pgn'
      parse_pgn(inpgn)
  
  main()
  </code></pre>
  <p><strong>sample.pgn</strong></p>
  <pre><code>[Result &quot;*&quot;]
  
  1. e4 {[%clk 0:01:00]} 1... g6 {[%clk 0:01:00]} 
  2. e5 {[%clk 0:00:59.2]} 2... Bg7 {[%clk 0:00:59.9]} 
  3. f4 {[%clk 0:00:58.4]} 3... d6 {[%clk 0:00:59.8]}
  </code></pre>
  <p><strong>Sample output</strong></p>
  <pre><code>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
  rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
  move: e2e4
  move_from: 12
  move_from_name: e2
  move_to: 28
  move_to_name: e4
  e2-e4
  piece: P
  
  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
  rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1
  move: g7g6
  move_from: 54
  move_from_name: g7
  move_to: 46
  move_to_name: g6
  g7-g6
  piece: p
  
  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
  rnbqkbnr/pppppp1p/6p1/8/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2
  move: e4e5
  move_from: 28
  move_from_name: e4
  move_to: 36
  move_to_name: e5
  e4-e5
  piece: P
  
  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
  rnbqkbnr/pppppp1p/6p1/4P3/8/8/PPPP1PPP/RNBQKBNR b KQkq - 0 2
  move: f8g7
  move_from: 61
  move_from_name: f8
  move_to: 54
  move_to_name: g7
  f8-g7
  piece: b
  
  r n b q k . n r
  p p p p p p b p
  . . . . . . p .
  . . . . P . . .
  . . . . . . . .
  . . . . . . . .
  P P P P . P P P
  R N B Q K B N R
  rnbqk1nr/ppppppbp/6p1/4P3/8/8/PPPP1PPP/RNBQKBNR w KQkq - 1 3
  move: f2f4
  move_from: 13
  move_from_name: f2
  move_to: 29
  move_to_name: f4
  f2-f4
  piece: P
  
  r n b q k . n r
  p p p p p p b p
  . . . . . . p .
  . . . . P . . .
  . . . . . P . .
  . . . . . . . .
  P P P P . . P P
  R N B Q K B N R
  rnbqk1nr/ppppppbp/6p1/4P3/5P2/8/PPPP2PP/RNBQKBNR b KQkq - 0 3
  move: d7d6
  move_from: 51
  move_from_name: d7
  move_to: 43
  move_to_name: d6
  d7-d6
  piece: p
  </code></pre>
  <p>Square 0 starts at lower left corner of the board or square a1.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-03-03T12:32:54.830Z
Answers.Text: Since OP wants "e2-e4", it might be nice to include the square names in the output instead of the square numbers: e.g.: `move.square_name(move.from_square)`
Answers.UserDisplayName: L. Scott Johnson
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-03-03T12:16:15.393Z
Answers.LastActivityDate: 2022-03-04T14:56:14.877Z
Answers.LastEditDate: 2022-03-04T14:56:14.877Z
Answers.UserDisplayName: ferdy
Body: <p>I want to read a PGN file and play those moves on my chess application. For example, the PGN structure that I have to read looks like this:</p>
  <pre><code>1. e4 {[%clk 0:01:00]} 1... g6 {[%clk 0:01:00]} 
  2. e5 {[%clk 0:00:59.2]} 2... Bg7 {[%clk 0:00:59.9]} 
  3. f4 {[%clk 0:00:58.4]} 3... d6 {[%clk 0:00:59.8]}
  </code></pre>
  <p>So the first move is <code>e4</code> by white. As human I can look at a chess board and tell that the only piece that can go to <code>e4</code> is the pawn currently on <code>e2</code>.</p>
  <p>But how do you know this when reading a PGN file?</p>
  <p>I need to feed my chess applications moves like <code>e2-e4</code>. As in, what ever piece is on <code>e2</code>, move it to <code>e4</code>. (By the notation I can at least tell that the piece is a pawn)</p>
  <p>So basically I need to know the starting position of the piece <code>e2</code>, and on what square it wants to land, <code>e4</code>.</p>
  <p>Is there a way to get this information from a PGN file? The only way I can think of is brute forcing to identify the only piece that can move to the location.</p>
  
Tags: <programming><pgn>
Title: How to find the piece to move when reading PGN file
ThreadText: # How to find the piece to move when reading PGN file
  
  (Asked by: username_0 on 2022-03-03)
  
  I want to read a PGN file and play those moves on my chess application. For example, the PGN structure that I have to read looks like this:
  1. e4 {[%clk 0:01:00]} 1... g6 {[%clk 0:01:00]} 
  2. e5 {[%clk 0:00:59.2]} 2... Bg7 {[%clk 0:00:59.9]} 
  3. f4 {[%clk 0:00:58.4]} 3... d6 {[%clk 0:00:59.8]}
  
  So the first move is e4 by white. As human I can look at a chess board and tell that the only piece that can go to e4 is the pawn currently on e2.
  But how do you know this when reading a PGN file?
  I need to feed my chess applications moves like e2-e4. As in, what ever piece is on e2, move it to e4. (By the notation I can at least tell that the piece is a pawn)
  So basically I need to know the starting position of the piece e2, and on what square it wants to land, e4.
  Is there a way to get this information from a PGN file? The only way I can think of is brute forcing to identify the only piece that can move to the location.
  
  **Tags:** programming, pgn
  
  
  ---
  
  ## 3 answers
  
  ### Answer by username_3 on 2022-03-03. Score: 7 | Accepted answer
  
  You can use a python chess library to parse the moves of a game in a pgn file.
  Code
  """
  pip install chess
  """
  
  import chess.pgn
  
  def parse_pgn(inpgn):
      with open(inpgn, encoding='utf-8') as h:
          while True:
              game = chess.pgn.read_game(h)
              if game is None:
                  break
  
              for node in game.mainline():
                  move = node.move 
                  pnode = node.parent
                  board = pnode.board()
  
                  move_from_sq = move.from_square
                  move_to_sq = move.to_square
  
                  print(board)
                  print(board.fen())
                  print(f'move: {move}')
                  print(f'move_from: {move_from_sq}')
                  print(f'move_from_name: {chess.SQUARE_NAMES[move_from_sq]}')
                  print(f'move_to: {move_to_sq}')
                  print(f'move_to_name: {chess.SQUARE_NAMES[move_to_sq]}')
                  print(f'{chess.SQUARE_NAMES[move_from_sq]}-{chess.SQUARE_NAMES[move_to_sq]}')
                  print(f'piece: {board.piece_at(move.from_square).symbol()}')
                  print()
  
  def main():
      inpgn = 'sample.pgn'
      parse_pgn(inpgn)
  
  main()
  
  sample.pgn
  [Result "*"]
  
  1. e4 {[%clk 0:01:00]} 1... g6 {[%clk 0:01:00]} 
  2. e5 {[%clk 0:00:59.2]} 2... Bg7 {[%clk 0:00:59.9]} 
  3. f4 {[%clk 0:00:58.4]} 3... d6 {[%clk 0:00:59.8]}
  
  Sample 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
  rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
  move: e2e4
  move_from: 12
  move_from_name: e2
  move_to: 28
  move_to_name: e4
  e2-e4
  piece: P
  
  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
  rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1
  move: g7g6
  move_from: 54
  move_from_name: g7
  move_to: 46
  move_to_name: g6
  g7-g6
  piece: p
  
  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
  rnbqkbnr/pppppp1p/6p1/8/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2
  move: e4e5
  move_from: 28
  move_from_name: e4
  move_to: 36
  move_to_name: e5
  e4-e5
  piece: P
  
  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
  rnbqkbnr/pppppp1p/6p1/4P3/8/8/PPPP1PPP/RNBQKBNR b KQkq - 0 2
  move: f8g7
  move_from: 61
  move_from_name: f8
  move_to: 54
  move_to_name: g7
  f8-g7
  piece: b
  
  r n b q k . n r
  p p p p p p b p
  . . . . . . p .
  . . . . P . . .
  . . . . . . . .
  . . . . . . . .
  P P P P . P P P
  R N B Q K B N R
  rnbqk1nr/ppppppbp/6p1/4P3/8/8/PPPP1PPP/RNBQKBNR w KQkq - 1 3
  move: f2f4
  move_from: 13
  move_from_name: f2
  move_to: 29
  move_to_name: f4
  f2-f4
  piece: P
  
  r n b q k . n r
  p p p p p p b p
  . . . . . . p .
  . . . . P . . .
  . . . . . P . .
  . . . . . . . .
  P P P P . . P P
  R N B Q K B N R
  rnbqk1nr/ppppppbp/6p1/4P3/5P2/8/PPPP2PP/RNBQKBNR b KQkq - 0 3
  move: d7d6
  move_from: 51
  move_from_name: d7
  move_to: 43
  move_to_name: d6
  d7-d6
  piece: p
  
  Square 0 starts at lower left corner of the board or square a1.
  
  > **Comments:**
  > **username_4**: Since OP wants "e2-e4", it might be nice to include the square names in the output instead of the square numbers: e.g.: `move.square_name(move.from_square)`  
  
  ---
  
  ### Answer by username_1 on 2022-03-04. Score: 1
  
  I'm confused by this statement:
  
  > I need to feed my chess applications moves like e2-e4.
  
  Why? Computers that can read pgn files will understand the moves as they are formated.
  
  If you're inputting them manually, the notation works fine too. People play entire games blindfolded on the same notation. As the you go down the list of moves, the next move is played based on the state of the board from the previous move. That is how algebraic lines have always worked.
  
  
  ---
  
  ### Answer by username_2 on 2022-03-03. Score: -1
  
  PGN files are intended to be read and used by computer programs, not humans. So, yes, the only way to do what you're asking is to brute-force search to make sure there's only one piece that can reach the destination square.
  
  
  ---
  
  