Most chess software tools generally allow for importing/exporting between any of their own formats for chess games or positions or whatever and PGN. Lucas Chess seems to be, for the most part, no exception; however, while it allows for importing from PGN to its Personal Opening Guide structure (.pgo files), it oddly doesn’t have an option to export in the other direction. I’m not a Lucas Chess user myself, but I stumbled upon that fact in a forum post from someone wanting to export their .pgo file to PGN for use in some other chess software, and asking if someone could program a converter for them.
That piqued my curiosity, so here I’ll lay out a quick way to get from a .pgo file to a standard .pgn file that can be imported to other programs, using nothing but an R script and David Barnes’ free pgn-extract utility.
It turns out that each .pgo file is just a SQLite database containing a single table called GUIDE. Some of the columns of the GUIDE table look like this:
XPV PV POS
--- -- ---
DT c2c4 1
DTn^ e7e5 2
DTn^;L b1c3 3
DTn^;Lxg g8f6 4
DTn^;Lxg@O g1f3 5
DTn^;Lxg@Osd b8c6 6
DTn^;Lxg@OsdFN e2e3 7
DTn^;Lxg@OsdFNwS f8b4 8
As can be seen, the XPV column contains strings that encode sequences of moves (in some encoding scheme that we don’t need to worry about), and the corresponding PV entry gives the final move of the sequence in long algebraic notation. The XPV for the eighth entry above encodes the sequence (in standard algebraic notation) 1.c4 e5 2.Nc3 Nf6 3.Nf3 Nc6 4.e3 Bb4. Ultimately, we need to get all of the move sequences contained in the GUIDE table into this standard algebraic notation that .pgn files use. We do this in two steps: first an R script that constructs the sequences in long algebraic notation, and then using pgn-extract to convert that to a proper .pgn file that can be imported and used freely.
The following R script converts a file called lucas_guide.pgo
into a file called intermediate_output.txt
that consists of all move sequences from the GUIDE table, presented in long algebraic notation.
## Path to your Lucas Chess .pgo file yourPGOfile <- "lucas_guide.pgo" ## Path to the output file for this script, which will then feed to ## pgn-extract outputFilePath <- "intermediate_output.txt" library(RSQLite) ## Use the RSQLite package to read the .pgo chess content into a data ## frame con <- dbConnect(drv=RSQLite::SQLite(), dbname=yourPGOfile) openingGuide <- dbGetQuery(conn=con, statement="SELECT * FROM 'GUIDE'") dbDisconnect(con) ## We're only going to work with a couple of columns openingGuide <- openingGuide[,c("XPV","PV")] ## Determine which moves in the guide are terminal (end of a line) allXPV <- openingGuide$XPV isEndOfLine <- function(x) { 1-max(sapply(allXPV, FUN=function(y){grepl(x,y,fixed=TRUE) & !(x==y)})) } openingGuide$isEndOfLine <- sapply(openingGuide$XPV,FUN=isEndOfLine) endsOfLines <- openingGuide[openingGuide$isEndOfLine>0,]$XPV ## For each terminal move, reconstruct the line that leads to it, in ## long algebraic notation, and add a "*" character at the end to ## separate the lines as "games" in a file allLines <- character() for (j in 1:length(endsOfLines)) { aux <- openingGuide aux$includeInLine <- sapply(openingGuide$XPV, FUN=function(x) { grepl(x,endsOfLines[j],fixed=TRUE)}) aux <- aux[aux$includeInLine,] aux <- aux[with(aux,order(XPV)),] allLines[[j]] <- paste(paste(aux$PV,collapse=' '),'*',sep=' ') } ## Write the lines/games to an output file, to feed into pgn-extract fileConn<-file(outputFilePath) writeLines(allLines, fileConn) close(fileConn)
Barnes’ pgn-extract utility can then convert intermediate_output.txt
into a standard .pgn file final_output.pgn
as follows:
pgn-extract --output final_output.pgn intermediate_output.txt
That’s all there is to it, as long as you are after just the moves, and not, say, textual comments or NAGs that were included in the opening guide. Those could be had too, by enhancing the R script above to use appropriately the NAG and COMMENT columns that are part of the GUIDE table, but I leave that to any interested party.