Answers.Body: <p>For loading Stockfish using python-chess and evaluating a PGN input see these already answered posts: </p>
  
  <ul>
  <li><a href="https://chess.stackexchange.com/q/18182/3594">Stockfish evaluation of a position from PGN</a> or </li>
  <li><a href="https://chess.stackexchange.com/q/15723/3594">Returning scores for all possible moves from a chess engine</a></li>
  </ul>
  
  <p>For Adding comments in between moves according to standard PGN formatting, you can use <code>node.comment</code> as follows:</p>
  
  <p>Let's take a sample PGN file (<a href="https://2700chess.com/games/svidler-caruana-r1-karlsruhe-2019-04-20" rel="nofollow noreferrer">Svidler vs Caruana Grenke 2019</a>) from <a href="http://theweekinchess.com/a-year-of-pgn-game-files" rel="nofollow noreferrer">TWIC</a>, load it up and add a comment to the first move:</p>
  
  <pre><code>import chess
  import chess.pgn
  
  pgnfilename = 'samplepgn.txt'
  with open(pgnfilename) as f:
      game = chess.pgn.read_game(f)
  
  node = game.variations[0]
  node.comment = 'this is a test comment'
  print game
  </code></pre>
  
  <p>and the output is:</p>
  
  <pre><code>[Event "GRENKE Chess Classic 2019"]
  [Site "Karlsruhe/Baden Baden GER"]
  [Date "2019.04.20"]
  [Round "1.2"]
  [White "Svidler, Peter"]
  [Black "Caruana, Fabiano"]
  [Result "1/2-1/2"]
  [WhiteTitle "GM"]
  [BlackTitle "GM"]
  [WhiteElo "2735"]
  [BlackElo "2819"]
  [ECO "B33"]
  [Opening "Sicilian"]
  [Variation "Pelikan (Lasker/Sveshnikov) variation"]
  [WhiteFideId "4102142"]
  [BlackFideId "2020009"]
  [EventDate "2019.04.20"]
  
  1. e4 { this is a test comment } 1... c5 2. Nf3 Nc6 ....
  </code></pre>
  
  <p>and if you want to write the output to a file (assuming <code>python 2.x</code>):</p>
  
  <pre><code>with open("testpgn.txt", "w") as fgame:
      print &gt;&gt; fgame, game
  </code></pre>
  
  <p>You should be able to take it from here. For any additional info, please have a look at the official <a href="https://python-chess.readthedocs.io/en/latest/pgn.html#" rel="nofollow noreferrer">documentations of python-chess</a>.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-05-14T20:40:22.770Z
Answers.Text: Thank you! I think I can iterate through nodes, check the evaluations and determine if the move was a mistake or something, right? Maybe chess.com do it that way...
Answers.UserDisplayName: Guilherme do Valle
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-05-14T20:52:22.143Z
Answers.Text: You're welcome! I don't know how it is implemented on the chess.com website, I'm showing you how to do it using free software in python with the python-chess module. For iterating over moves, `variations` (of the `chess.pgn.GameNode` class) contains all the child nodes, so just loop over all nodes and evaluate them (just print them to see it clearly for yourself `for var in game.variations: print var`). See the linked-in posts for examples and related discussions.
Answers.UserDisplayName: Ellie
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-05-14T20:19:34.923Z
Answers.LastActivityDate: 2019-05-14T20:19:34.923Z
Answers.UserDisplayName: Ellie
Answers.Body: <p>Have you looked at <a href="https://github.com/rpdelaney/python-chess-annotator" rel="nofollow noreferrer">python-chess-annotator</a>? I think it does pretty much what you want, and if not, it might be easier to modify it than to start from scratch. It's based on <code>python-chess</code>, too.</p>
  
  <p>I'll copy its usage example here to make this answer a bit more self-contained:</p>
  
  <pre><code>$ python3 -m annotator -h
  usage: annotator [-h] --file FILE.pgn [--engine ENGINE] [--gametime MINUTES]
                   [--threads THREADS] [--verbose]
  
  takes chess games in a PGN file and prints annotations to standard output
  
  optional arguments:
    -h, --help            show this help message and exit
    --file FILE.pgn, -f FILE.pgn
                          input PGN file
    --engine ENGINE, -e ENGINE
                          analysis engine (default: stockfish)
    --gametime MINUTES, -g MINUTES
                          how long to spend on each game (default: 1)
    --threads THREADS, -t THREADS
                          threads for use by the engine (default: 1)
    --verbose, -v         increase verbosity
  
  $ python3 -m annotator -f caruana-kasparov.pgn -g 15
  [Event "Ultimate Blitz Challenge"]
  [Site "St. Louis, MO USA"]
  [Date "2016.04.29"]
  [Round "18.1"]
  [White "Fabiano Caruana"]
  [Black "Garry Kasparov"]
  [Result "0-1"]
  [EventDate "2016.04.28"]
  [ECO "A05"]
  [WhiteElo "2795"]
  [BlackElo "2812"]
  [PlyCount "74"]
  [Opening "King's Indian Attack: Symmetrical Defense"]
  [WhiteACPL "252"]
  [BlackACPL "141"]
  [Annotator "Stockfish 8 64 POPCNT"]
  
  { Stockfish 8 64 POPCNT } 1. Nf3 Nf6 2. g3 g6 { A05 King's Indian Attack:
  Symmetrical Defense } 3. Bg2 Bg7 4. O-O O-O 5. c4 d6 6. b3 e5 7. Bb2 c5 8. e3
  Nc6 9. Nc3 Bf5 10. d4 e4 11. Ne1 Re8 12. Nc2 h5 13. Qd2 h4 14. Ba3 $6 { -1.13 }
  ( 14. h3 g5 15. g4 Bg6 16. Rad1 Qe7 17. Qe2 a6 18. Ba3 a5 { 0.19/25 } ) 14...
  b6 $6 { -0.04 } ( 14... Nh7 15. Nd5 Ng5 16. Bb2 Rc8 17. Rac1 Ne7 18. Nf4 h3 19.
  Bh1 { -1.11/24 } ) 15. Rfd1 $6 { -1.15 } ( 15. h3 d5 16. g4 Be6 17. cxd5 Nxd5
  18. Nxe4 f5 19. gxf5 gxf5 { 0.00/26 } ) 15... Bg4 16. Rdc1 Qd7 17. b4 Qf5 18.
  Bb2 Rad8 19. Nb5 Bf3 20. d5 Ne5 $6 { -1.66 } ( 20... Nxb4 21. Ne1 Bxg2 22.
  Nxg2 Nd3 23. Nxh4 Qh3 24. Bxf6 Bxf6 25. f4 { -3.14/25 } ) 21. Bxe5 Rxe5 22.
  Ne1 hxg3 23. fxg3 Bh6 24. Rab1 Kg7 $6 { -1.08 } ( 24... Qh5 25. Rb3 Rf5 26.
  bxc5 dxc5 27. Rc2 Ng4 28. h3 Bxg2 29. Kxg2 { -2.48/24 } ) 25. Rb3 Qh5 26. h3
  $6 { -3.08 } ( 26. bxc5 bxc5 27. Nxa7 Rh8 28. h4 Qg4 29. Nc6 Rh5 30. Qf2
  Bd1 { -2.00/23 } ) 26... Nh7 $2 { -1.37 } ( 26... Rg5 27. Qf2 { -2.89/24 })
  27. g4 Bxg4 28. hxg4 Qxg4 29. Qd1 $4 { -5.69 } ( 29. Qb2 Ng5 30. Nxd6 Qg3
  31. Nf5+ gxf5 32. Kf1 Nf3 33. Qf2 Nh2+ { -2.30/24 } ) 29... Qg3 30. Qe2 Ng5
  31. Kh1 Rh8 32. Nxd6 Kg8 33. bxc5 Bf8+ 34. Kg1 Nh3+ 35. Kf1 Bxd6
  36. cxd6 Rf5+ 37. Nf3 Rxf3+ 0-1
  </code></pre>
  
  <p>(Note: I'm not the author or affiliated to this project in any way, so for further questions I suggest contacting the author via github.)</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-05-15T12:59:48.710Z
Answers.LastActivityDate: 2019-05-15T12:59:48.710Z
Answers.UserDisplayName: itub
Body: <p>I want, with Python-chess, to evaluate any movement of some game and generate the PGN with analysis, as Chess.com does in its analysis.</p>
  
  <p>For example, i played one game with fools mate and they generate that PGN:</p>
  
  <pre><code>[Event "?"]
  [Site "?"]
  [Date "????.??.??"]
  [Round "?"]
  [White "?"]
  [Black "?"]
  [Result "1-0"]
  
  1. e4 f6 {INACCURACY (+1.03)} ({(+0.16) The best move was} 1... e6 2. d4 d5 3.
  exd5 exd5 4. Bd3 Nf6 5. Nf3 Bd6 6. O-O O-O 7. Re1 Be6 8. h3 Re8 9. Nc3 c6 10.
  Ne2 Qc7 11. Be3 Nbd7 12. Qc1 c5 13. c3 c4 14. Bc2 Ne4 15. Bf4 f6 16. Bxd6 Qxd6
  17. Nd2 Nxd2 18. Qxd2 Nb6 19. Ng3 Bd7 20. Rxe8+ Rxe8 21. Re1 Rxe1+ 22. Qxe1) 2.
  d4 g5?? ± {BLUNDER (♔ Mate in 1)} ({(+0.93) The best move was} 2... e6 3. Bb5
  Ne7 4. Nc3 g6 5. Nf3 Bg7 6. h4 a6 7. Be2 d5 8. h5 gxh5 9. Rxh5 dxe4 10. Nxe4 f5
  11. Nc5 Nbc6 12. c3 e5 13. dxe5) 3. Qh5# 1-0
  </code></pre>
  
  <p>I like to show the evaluation of any move (if its an good move, or excellent, blunder, book-move ...), like they do. </p>
  
  <p>I know how to load any PGN game and process it, generating String from PGN, like:</p>
  
  
  
  <pre><code>import chess
  import chess.pgn
  
  pgn = open("game path")
  board = game.board()
  for move in game.mainline_moves():
      board.push(move)
  exporter = chess.pgn.StringExporter(headers=True)
  
  pgn_string = game.accept(exporter)
  print(pgn_string) ## Here is the string with the pgn!
  
  
  </code></pre>
  
  <p>Basically: i want to generate a String PGN from an evaluated chess game.</p>
  
Tags: <engines><analysis><software><programming><pgn>
Title: How to evaluate and comment moves in PGN format?
ThreadText: # How to evaluate and comment moves in PGN format?
  
  (Asked by: username_0 on 2019-05-14)
  
  I want, with Python-chess, to evaluate any movement of some game and generate the PGN with analysis, as Chess.com does in its analysis.
  For example, i played one game with fools mate and they generate that PGN:
  [Event "?"]
  [Site "?"]
  [Date "????.??.??"]
  [Round "?"]
  [White "?"]
  [Black "?"]
  [Result "1-0"]
  
  1. e4 f6 {INACCURACY (+1.03)} ({(+0.16) The best move was} 1... e6 2. d4 d5 3.
  exd5 exd5 4. Bd3 Nf6 5. Nf3 Bd6 6. O-O O-O 7. Re1 Be6 8. h3 Re8 9. Nc3 c6 10.
  Ne2 Qc7 11. Be3 Nbd7 12. Qc1 c5 13. c3 c4 14. Bc2 Ne4 15. Bf4 f6 16. Bxd6 Qxd6
  17. Nd2 Nxd2 18. Qxd2 Nb6 19. Ng3 Bd7 20. Rxe8+ Rxe8 21. Re1 Rxe1+ 22. Qxe1) 2.
  d4 g5?? ± {BLUNDER (♔ Mate in 1)} ({(+0.93) The best move was} 2... e6 3. Bb5
  Ne7 4. Nc3 g6 5. Nf3 Bg7 6. h4 a6 7. Be2 d5 8. h5 gxh5 9. Rxh5 dxe4 10. Nxe4 f5
  11. Nc5 Nbc6 12. c3 e5 13. dxe5) 3. Qh5# 1-0
  
  I like to show the evaluation of any move (if its an good move, or excellent, blunder, book-move ...), like they do. 
  I know how to load any PGN game and process it, generating String from PGN, like:
  import chess
  import chess.pgn
  
  pgn = open("game path")
  board = game.board()
  for move in game.mainline_moves():
      board.push(move)
  exporter = chess.pgn.StringExporter(headers=True)
  
  pgn_string = game.accept(exporter)
  print(pgn_string) ## Here is the string with the pgn!
  
  
  
  Basically: i want to generate a String PGN from an evaluated chess game.
  
  **Tags:** engines, analysis, software, programming, pgn
  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_1 on 2019-05-14. Score: 2 | Accepted answer
  
  For loading Stockfish using python-chess and evaluating a PGN input see these already answered posts: 
  
  Stockfish evaluation of a position from PGN or 
  Returning scores for all possible moves from a chess engine
  
  For Adding comments in between moves according to standard PGN formatting, you can use node.comment as follows:
  Let's take a sample PGN file (Svidler vs Caruana Grenke 2019) from TWIC, load it up and add a comment to the first move:
  import chess
  import chess.pgn
  
  pgnfilename = 'samplepgn.txt'
  with open(pgnfilename) as f:
      game = chess.pgn.read_game(f)
  
  node = game.variations[0]
  node.comment = 'this is a test comment'
  print game
  
  and the output is:
  [Event "GRENKE Chess Classic 2019"]
  [Site "Karlsruhe/Baden Baden GER"]
  [Date "2019.04.20"]
  [Round "1.2"]
  [White "Svidler, Peter"]
  [Black "Caruana, Fabiano"]
  [Result "1/2-1/2"]
  [WhiteTitle "GM"]
  [BlackTitle "GM"]
  [WhiteElo "2735"]
  [BlackElo "2819"]
  [ECO "B33"]
  [Opening "Sicilian"]
  [Variation "Pelikan (Lasker/Sveshnikov) variation"]
  [WhiteFideId "4102142"]
  [BlackFideId "2020009"]
  [EventDate "2019.04.20"]
  
  1. e4 { this is a test comment } 1... c5 2. Nf3 Nc6 ....
  
  and if you want to write the output to a file (assuming python 2.x):
  with open("testpgn.txt", "w") as fgame:
      print >> fgame, game
  
  You should be able to take it from here. For any additional info, please have a look at the official documentations of python-chess.
  
  > **Comments:**
  > **username_0**: Thank you! I think I can iterate through nodes, check the evaluations and determine if the move was a mistake or something, right? Maybe chess.com do it that way...  
  > **username_1**: You're welcome! I don't know how it is implemented on the chess.com website, I'm showing you how to do it using free software in python with the python-chess module. For iterating over moves, `variations` (of the `chess.pgn.GameNode` class) contains all the child nodes, so just loop over all nodes and evaluate them (just print them to see it clearly for yourself `for var in game.variations: print var`). See the linked-in posts for examples and related discussions.  
  
  ---
  
  ### Answer by username_2 on 2019-05-15. Score: 3
  
  Have you looked at python-chess-annotator? I think it does pretty much what you want, and if not, it might be easier to modify it than to start from scratch. It's based on python-chess, too.
  I'll copy its usage example here to make this answer a bit more self-contained:
  $ python3 -m annotator -h
  usage: annotator [-h] --file FILE.pgn [--engine ENGINE] [--gametime MINUTES]
                   [--threads THREADS] [--verbose]
  
  takes chess games in a PGN file and prints annotations to standard output
  
  optional arguments:
    -h, --help            show this help message and exit
    --file FILE.pgn, -f FILE.pgn
                          input PGN file
    --engine ENGINE, -e ENGINE
                          analysis engine (default: stockfish)
    --gametime MINUTES, -g MINUTES
                          how long to spend on each game (default: 1)
    --threads THREADS, -t THREADS
                          threads for use by the engine (default: 1)
    --verbose, -v         increase verbosity
  
  $ python3 -m annotator -f caruana-kasparov.pgn -g 15
  [Event "Ultimate Blitz Challenge"]
  [Site "St. Louis, MO USA"]
  [Date "2016.04.29"]
  [Round "18.1"]
  [White "Fabiano Caruana"]
  [Black "Garry Kasparov"]
  [Result "0-1"]
  [EventDate "2016.04.28"]
  [ECO "A05"]
  [WhiteElo "2795"]
  [BlackElo "2812"]
  [PlyCount "74"]
  [Opening "King's Indian Attack: Symmetrical Defense"]
  [WhiteACPL "252"]
  [BlackACPL "141"]
  [Annotator "Stockfish 8 64 POPCNT"]
  
  { Stockfish 8 64 POPCNT } 1. Nf3 Nf6 2. g3 g6 { A05 King's Indian Attack:
  Symmetrical Defense } 3. Bg2 Bg7 4. O-O O-O 5. c4 d6 6. b3 e5 7. Bb2 c5 8. e3
  Nc6 9. Nc3 Bf5 10. d4 e4 11. Ne1 Re8 12. Nc2 h5 13. Qd2 h4 14. Ba3 $6 { -1.13 }
  ( 14. h3 g5 15. g4 Bg6 16. Rad1 Qe7 17. Qe2 a6 18. Ba3 a5 { 0.19/25 } ) 14...
  b6 $6 { -0.04 } ( 14... Nh7 15. Nd5 Ng5 16. Bb2 Rc8 17. Rac1 Ne7 18. Nf4 h3 19.
  Bh1 { -1.11/24 } ) 15. Rfd1 $6 { -1.15 } ( 15. h3 d5 16. g4 Be6 17. cxd5 Nxd5
  18. Nxe4 f5 19. gxf5 gxf5 { 0.00/26 } ) 15... Bg4 16. Rdc1 Qd7 17. b4 Qf5 18.
  Bb2 Rad8 19. Nb5 Bf3 20. d5 Ne5 $6 { -1.66 } ( 20... Nxb4 21. Ne1 Bxg2 22.
  Nxg2 Nd3 23. Nxh4 Qh3 24. Bxf6 Bxf6 25. f4 { -3.14/25 } ) 21. Bxe5 Rxe5 22.
  Ne1 hxg3 23. fxg3 Bh6 24. Rab1 Kg7 $6 { -1.08 } ( 24... Qh5 25. Rb3 Rf5 26.
  bxc5 dxc5 27. Rc2 Ng4 28. h3 Bxg2 29. Kxg2 { -2.48/24 } ) 25. Rb3 Qh5 26. h3
  $6 { -3.08 } ( 26. bxc5 bxc5 27. Nxa7 Rh8 28. h4 Qg4 29. Nc6 Rh5 30. Qf2
  Bd1 { -2.00/23 } ) 26... Nh7 $2 { -1.37 } ( 26... Rg5 27. Qf2 { -2.89/24 })
  27. g4 Bxg4 28. hxg4 Qxg4 29. Qd1 $4 { -5.69 } ( 29. Qb2 Ng5 30. Nxd6 Qg3
  31. Nf5+ gxf5 32. Kf1 Nf3 33. Qf2 Nh2+ { -2.30/24 } ) 29... Qg3 30. Qe2 Ng5
  31. Kh1 Rh8 32. Nxd6 Kg8 33. bxc5 Bf8+ 34. Kg1 Nh3+ 35. Kf1 Bxd6
  36. cxd6 Rf5+ 37. Nf3 Rxf3+ 0-1
  
  (Note: I'm not the author or affiliated to this project in any way, so for further questions I suggest contacting the author via github.)
  
  
  ---
  
  