niklasf / python-chess

A chess library for Python, with move generation and validation, PGN parsing and writing, Polyglot opening book reading, Gaviota tablebase probing, Syzygy tablebase probing, and UCI/XBoard engine communication
https://python-chess.readthedocs.io/en/latest/
GNU General Public License v3.0
2.42k stars 529 forks source link

Generate FEN from current position #733

Closed ExtremeCoolDude closed 3 years ago

ExtremeCoolDude commented 3 years ago

Is there a way to generate FEN at the current position when we only know the sequence of moves ?

According to docs fen from Board class should get representation of current position but it always returns starting position.

I'm trying to generate fen from a file that has no fen in its header. Then I want to export Fen + notation + comments on a new line where fen is separated by a tab and the whole game is one long string then another game on a new line.

Reading a pgn returns an array of chess.pgn.Game objects. I tried to override the visit_header function from GameBuilder but so far succeeded only in wiping out all the headers in output files.

ExtremeCoolDude commented 3 years ago

I figured out the FEN part, you first have to call board() on the game object, then board.fen() works. Now I only need help how to export custom headers, in a custom format for example FEN + \t + mainline moves, then on newline same thing.

ExtremeCoolDude commented 3 years ago

Turned out into a simple enough task :


  if game:
     board = game.board()
            fens = board.fen()
            exporter = chess.pgn.StringExporter(headers=False, variations=True,comments = True, columns= None)
            move_string = fens + "\t" + game.accept(exporter) + "\n"

But ran into another issue, even though the columns is None, if there is a newline within a { } comment, there is linebreak. This isn't good since I'm trying to import the resulting txt file into anki and anki interprets linebreak as a new anki card.

ExtremeCoolDude commented 3 years ago

Now I need help to dorstrip() somewhere in the source code that parses pgn comments.

niklasf commented 3 years ago

To do so at export time, you can subclass StringExporter.

Here's the base implementation, that you could tweak to your liking.

class MyStringExporter(chess.pgn.StringExporter):
    def visit_comment(self, comment):
        if self.comments and (self.variations or not self.variation_depth):
            self.write_token("{ " + comment.replace("}", "").strip() + " } ")
            self.force_movenumber = True

exporter = MyStringExporter(...)
ExtremeCoolDude commented 3 years ago

Thanks a lot.