Neonira
by Neonira

Categories

  • games
  • EN

Tags

  • chess
  • computer
  • R

Experimenting rchess package

This is the second post of a serie, dedicated to rchess R package.
This week we aim to produce chess game half-move images and to proceed to a movie montage in order to get a video representative of the full chess game. In cas you missed first part, you may read part 1 here

Producing chess half-move images

From a pgn chess file, using rchess, we should be able to load the game, get the FEN string for each of its positions and to produce a ggplot to be saved under png image format. Pay attention to not confuse pgn and png. To do so, I’ll use following R code, and use a short file I played with black side on lichess.org

fn <- file.path("~/pgn", '20180410_Chessmonkey1_vs_neonira.P4oDzgTw.pgn')
pgn <- readLines(fn, warn = FALSE)
pgn <- paste(pgn, collapse = "\n")
chsspgn <- Chess$new()
if (!chsspgn$load_pgn(pgn)) stop(paste('unable to load pgn file', fn))

moviepgn <- Chess$new()
pl <- chsspgn$history(verbose = TRUE)

rv <- sapply(0:nrow(pl), function(n) {
    if (n > 0) moviepgn$move(pl[n, 'san'])
    afen <- moviepgn$fen()
    z <- ggchessboard(fen = afen,
                      cellcols = c("#8ca2ad", "#dee3e6"),
                      perspective = 'black',
                      piecesize = 10)
    list(z)
  }, simplify = FALSE)

# a couple of convenient functions
ensureFilenameExtension <- function(fn, ext) paste0(sub(paste0(ext,'$'), '', fn, perl = TRUE), ext)
catn <- function(...) cat(..., '\n')

# a function to save a one or two plots to a single image, according to various layouts
s2png <- function(fn, p1, p2, tms = 0,  grid = FALSE) {
  tfn = ensureFilenameExtension(fn, '.png')
  png(filename = tfb, width = 1200, height = 622) # width must be even for ffmpeg to work fine
  if (!grid) print(p1)
  else
    if (!is.na(p2[1])) grid.arrange(p1, p2, nrow = 1) else grid.arrange(p1, nrow = 1)
  Sys.sleep(tms)
  dev.off()
  catn(fn)
  tfn
}


# produce images 
invisible(sapply(seq(length(rv)), function(i) {
    fn <- sprintf('png-%03d.png', i)
    s2png(fn, rv[[i]], NA)
}))

produced image samples

image #5 image #14 image #15

So far, so good. We have now an image for each hal-move played in the original chess game. Just need to proceed to a quick movie montage to create a .mp4 video file. To do so, let’s first create following bash script.

#!/bin/bash 
[ "${DEBUG}" = "${0##*/}" ] && set -x 

echo "creation mp4 movie"
ffmpeg -r 1 -i png-%03d.png -c:v libx264 -vf "fps=25,format=yuv420p" out.mp4 -y

[ "${DEBUG}" = "${0##*/}" ] && set +x 
exit 0

You have to save it into a bash file and to run it, in the folder where you produced your chess half-move image files. This will produce a file named out.mp4. See below.

So, we just created a kind of standard video movie to display a chess game. Nothing really new, but it works fine, and most of all, it opens some opportunities of more advanced video montage.

You’ll ask why not using animation R package. Just because, I experienced it several times and found it to be very slow, compared to bash script invocation. Just a matter of performance on my machine. Another reason, is that it helps in tracking issues. Here, it is easy to identify the issue. If it is a content issue, then it probably comes from R processing. If it is a montage issue, it will probably have ffmpeg as origin. If we were using animation R package, resolving such issues won’t be as easy.

Next part, to come

We’ll create a chessboard influence analysis system that will produce image showing influence zones on chessboard and that could display various interesting information to ease understanding of some chess moves. See you on part 3.

Note

Images made using ggplot R base package.
Movie montage achieved by external shell script instrumenting ffmpeg as it appeared to be much faster and reliable than thru animation R package.