Most of this post is adapted from Joshua Kunst’s excellent post Visualizing chess data with ggplot. It was then combined with the gganimate package to make an animated variant of one of the figures. gganimate can be installed with:
devtools::install_github("dgrtwo/gganimate")
We start by reproducing the dfmoves object from that blog post:
library(rchess)
library(dplyr)
library(ggplot2)
library(foreach)
library(doParallel)
library(gganimate)
data(chesswc)
chesswc <- chesswc %>%
filter(event == "FIDE World Cup 2015") %>%
mutate(game_id = row_number())
workers <- makeCluster(parallel::detectCores())
registerDoParallel(workers)
extract_history <- function(x){
chss <- Chess$new()
chss$load_pgn(x$pgn)
chss$history_detail()
}
dfmoves <- chesswc %>%
select(pgn, game_id) %>%
plyr::adply(.margins = 1, extract_history, .parallel = TRUE, .paropts = list(.packages = c("rchess"))) %>%
tbl_df()
We then generate the set of move paths:
dfboard <- rchess:::.chessboarddata() %>%
select(cell, col, row, x, y, cc)
dfpaths <- dfmoves %>%
left_join(dfboard %>% rename(from = cell, x.from = x, y.from = y),
by = "from") %>%
left_join(dfboard %>% rename(to = cell, x.to = x, y.to = y) %>% select(-cc, -col, -row),
by = "to") %>%
mutate(x_gt_y = abs(x.to - x.from) > abs(y.to - y.from),
xy_sign = sign((x.to - x.from)*(y.to - y.from)) == 1,
x_gt_y_equal_xy_sign = x_gt_y == xy_sign)
Now we customize to look at four pieces and to filter for White’s first 40 turns.
pieces <- c("White Queen", "c1 Bishop", "b1 Knight", "a1 Rook")
subpaths <- dfpaths %>%
mutate(turn = (number_move + 1) / 2) %>%
filter(turn <= 40, piece %in% pieces)
In our graph, we add the frame = turn and cumulative = TRUE aesthetic to the geom_curve, and we facet by the piece. This lets us create our animation:
curve_layer <- function(data, curvature) {
geom_curve(data = data,
aes(x = x.from, y = y.from, xend = x.to, yend = y.to, frame = turn, cumulative = TRUE),
position = position_jitter(width = 0.2, height = 0.2),
curvature = curvature, angle = -45, alpha = 0.02, color = "white", size = 1.05)
}
g <- ggplot() +
geom_tile(data = dfboard, aes(x, y, fill = cc), show.legend = FALSE) +
curve_layer(data = subpaths %>% filter(!x_gt_y_equal_xy_sign), curvature = -0.50) +
curve_layer(data = subpaths %>% filter(x_gt_y_equal_xy_sign), curvature = 0.50) +
scale_fill_manual(values = c("gray10", "gray20")) +
coord_equal() +
facet_wrap(~piece) +
ggtitle("Turn = ") +
theme_bw() +
theme(axis.text = element_blank(), axis.title = element_blank(),
axis.ticks = element_blank(), panel.grid = element_blank())
library(gganimate)
gg_animate(g, interval = .2)