2 Example Code

The R code below creates the animation, crunch point and final position of a game. In this instance the first World Championship game between Spassky and Fischer

First load the R packages needed

# libraries required to be loaded

library("rchess")
library("purrr")
library("magick")

Then download a PGN file
PGN (Portable Game Notation) is an easy-to-read format which records both the moves of the game (in standard algebraic notation) and any related data such the names of the players, the winner/loser, and date the game was played

One source is chessgames.com from where I downloaded the required file and saved to a URL

pgn <- "http://www.premiersoccerstats.com/chess/match.pgn"
pgn <- readLines(pgn, warn = FALSE)
pgn <- paste(pgn, collapse = "\n")
cat(pgn)
## [Event "Fischer - Spassky World Championship Match"]
## [Site "Reykjavik ISL"]
## [Date "1972.07.11"]
## [EventDate "?"]
## [Round "1"]
## [Result "1-0"]
## [White "Boris Spassky"]
## [Black "Robert James Fischer"]
## [ECO "E56"]
## [WhiteElo "?"]
## [BlackElo "?"]
## [PlyCount "111"]
## 
## 1. d4 Nf6 2. c4 e6 3. Nf3 d5 4. Nc3 Bb4 5. e3 O-O 6. Bd3 c5
## 7. O-O Nc6 8. a3 Ba5 9. Ne2 dxc4 10. Bxc4 Bb6 11. dxc5 Qxd1
## 12. Rxd1 Bxc5 13. b4 Be7 14. Bb2 Bd7 15. Rac1 Rfd8 16. Ned4
## Nxd4 17. Nxd4 Ba4 18. Bb3 Bxb3 19. Nxb3 Rxd1+ 20. Rxd1 Rc8
## 21. Kf1 Kf8 22. Ke2 Ne4 23. Rc1 Rxc1 24. Bxc1 f6 25. Na5 Nd6
## 26. Kd3 Bd8 27. Nc4 Bc7 28. Nxd6 Bxd6 29. b5 Bxh2 30. g3 h5
## 31. Ke2 h4 32. Kf3 Ke7 33. Kg2 hxg3 34. fxg3 Bxg3 35. Kxg3 Kd6
## 36. a4 Kd5 37. Ba3 Ke4 38. Bc5 a6 39. b6 f5 40. Kh4 f4
## 41. exf4 Kxf4 42. Kh5 Kf5 43. Be3 Ke4 44. Bf2 Kf5 45. Bh4 e5
## 46. Bg5 e4 47. Be3 Kf6 48. Kg4 Ke5 49. Kg5 Kd5 50. Kf5 a5
## 51. Bf2 g5 52. Kxg5 Kc4 53. Kf5 Kb4 54. Kxe4 Kxa4 55. Kd5 Kb5
## 56. Kd6 1-0

We now need to create all the board positions from the game in the form of FENS.
Forsyth–Edwards Notation (FEN) is a standard notation for describing a particular board position of a chess game. The purpose of FEN is to provide all the necessary information to restart a game from a particular position. This requires a function

get_fens <- function(pgn) {
  
  chss <- Chess$new()
  chss$load_pgn(pgn) # in package and demo but not well documented see chess.R for details
  
  moves <- chss$history()
  chss$reset()
  
  fens <- map_chr(moves, function(x) chss$move(x)$fen()) #62 eg fens[1] [1] "rnbqkbnr/pppppppp/8/8/3P4/8/PPP1PPPP/RNBQKBNR b KQkq d3 0 1"
  
  fens
  
}

fens <- get_fens(pgn)

## print an example

fens[9]
## [1] "rnbqk2r/ppp2ppp/4pn2/3p4/1bPP4/2N1PN2/PP3PPP/R1BQKB1R b KQkq - 0 5"

The crunch position in this game came after White’s 29th move. Here we identify the correct FEN and produce an image of the board

player <- "white"
move <- 29
gamemove <- 2 * (move-1) + (player != "white")
gamemove
## [1] 56
fens[gamemove]
## [1] "5k2/pp4pp/3bpp2/8/1P6/P2KP3/5PPP/2B5 w - - 0 29"
#Plots this position
ggchessboard(fens[gamemove])

# save to file
png("crunchMove.png")
ggchessboard(fens[gamemove])
dev.off()
## png 
##   2

Black took the Rook’s pawn and did not get sufficient compensation after it was trapped

The same procedure can be done for the final position. Here, Black cannot stop White from getting his pawn to the final rank

ggchessboard(fens[length(fens)])

png("finalPos.png")
ggchessboard(fens[length(fens)])
dev.off()
## png 
##   2

Finally an animation of the whole game can be created. This can take a while and needs another function

get_gif <- function(pgn, scale = "400x400", fps = 1) {
  
  fens <- get_fens(pgn)
  # fens <- head(fens)
  
  fens %>% 
    map(ggchessboard) %>% 
    map_chr(function(p){ 
      fl <- tempfile(fileext = ".jpg")
      ggplot2::ggsave(p, file = fl)
      fl
    }) %>% 
    image_read() %>% 
    image_scale(geometry = scale) %>% 
    image_animate(fps = 0.2,loop=1) # amended here to once every 5 seconds. Assumption just play through once - can refresh if necessary
  
  
}

## This takes a while and can be done offline
#gif <- get_gif(pgn)
#image_write(gif, "animation.gif") 

Here is the final version