Rob Herbison
Northeastern University
November 29, 2017


This is a portion of a Markov chain analysis on a collection of chess algebra. It is being actively modified so right now it is a lot of nonsense. The data has been cleaned. These are the twelve games between Deep Blue and Kasparov in order.

Expiremental Design

This is a demonstration of the methodology of Markov chain analysis on chess games. The goal is to uncover patterns in historical chess games. This is one expirement out of many possible using Markov chain analysis.

A chess game can be broken down into a collection of board positions including their proceeding move. While the total number of these states availible through legal moves is large, the space can be partitioned into more managebale states. These states are categorical and nonordinal making them difficult to work with using many established statistical methods. A markov chain analysis works well with these data sets and is effective at uncovering relationships between two nearby states.

The state space is {The Initial Board Position, Moves with a Capture and no Check, Moves with a Check and no Capture, Moves with Both Capture and Check, All Else}. Call these {I, X, P, A, E} for easy refference. This space was chosen because it is manageable and it describes some of the more notable events in a game that are easily measured.

By the rules of chess, the initial state, I, is transient. The board position can be subsequently reached legaly but, by design, that involves a move which changes the nature of the state. In competitive games it is unlikely the initial board position will ever be reached a second time.

The null hypothesis is that the probabilities of both captures and checks are independent of whether captures or checks occured in the previous move. The goal is to uncover clumping around captures in the game. Finaly, the intent is to leave all of my methodology scalable to allow the same code to work on a much larger collection of chess algebra.

Methodology

Here is a sample of the data from the first game:

x <- scan("C:/Users/robhe/Dropbox/Markov_Chess/Kasparov_Deep_Blue.txt", what="", sep="\n")
y <- strsplit(x, "[[:space:]]+")
y[[1]]
##  [1] "1.e4"     "c5"       "2.c3"     "d5"       "3.exd5"   "Qxd5"    
##  [7] "4.d4"     "Nf6"      "5.Nf3"    "Bg4"      "6.Be2"    "e6"      
## [13] "7.h3"     "Bh5"      "8.0-0"    "Nc6"      "9.Be3"    "cxd4"    
## [19] "10.cxd4"  "Bb4"      "11.a3"    "Ba5"      "12.Nc3"   "Qd6"     
## [25] "13.Nb5"   "Qe7"      "14.Ne5"   "Bxe2"     "15.Qxe2"  "0-0"     
## [31] "16.Rac1"  "Rac8"     "17.Bg5"   "Bb6"      "18.Bxf6"  "gxf6"    
## [37] "19.Nc4"   "Rfd8"     "20.Nxb6"  "axb6"     "21.Rfd1"  "f5"      
## [43] "22.Qe3"   "Qf6"      "23.d5"    "Rxd5"     "24.Rxd5"  "exd5"    
## [49] "25.b3"    "Kh8"      "26.Qxb6"  "Rg8"      "27.Qc5"   "d4"      
## [55] "28.Nd6"   "f4"       "29.Nxb7"  "Ne5"      "30.Qd5"   "f3"      
## [61] "31.g3"    "Nd3"      "32.Rc7"   "Re8"      "33.Nd6"   "Re1+"    
## [67] "34.Kh2"   "Nxf2"     "35.Nxf7+" "Kg7"      "36.Ng5+"  "Kh6"     
## [73] "37.Rxh7+"

I used R to read the text files and create the nested vectors holding the moves. For brevity I have ommited this step from the report.

You will notice that I do not use the normal convention for numbering chess games. For computational purposes I count each piece moved as one move. Absent from the data, it is assumed that the board always starts at the initial state. This is the 0th state. By the rules of chess and under my partition of the possible board positions, the zeroth move will always go to the else category which is consistent with the data. My methodology assumes this to ease computing.

A note on chess algebra: Each entry represents moves with the numbered entries representing white’s turn. They appear to give incomplete information but it is standard to remove any characters not necessary to prevent ambiguity. In the case of both captures and checks the symbols are left in for clarity. If an “x” is in the entry, a piece was taken. If a “+” is in the entry, the move left a king in check. Interesting Markov chain analyses on some other state spaces are more difficult due to the peculiarities of chess algebra.

Below are functions to determine what characteristics are happening at each entry. These form truth tables of the same dimensions as the chess data entries. Note that only oCaptures, oChecks, Both, and Else correspond to the state space.

States <- c("Initial", "oCapture", "oCheck", "Both", "Else")
isX <- function(y) {
  n <- 1:length(y)
  X <- c()
  for(game in n) {X[[game]] <- grepl("x", y[[game]], fixed = TRUE)}
  return(X)
}

isP <- function(y) {
  n <- 1:length(y)
  P <- c()
  for(game in n) {P[[game]] <- grepl("+", y[[game]], fixed = TRUE)}
  return(P)
}

Captures <- isX(y)
Checks <- isP(y)

isoX <- function(y) {
  n <- 1:length(y)
  oX <- c()
  for(game in n) {oX[[game]] <- Captures[[game]] & (! Checks[[game]])}
  return(oX)
}

isoP <- function(y) {
  n <- 1:length(y)
  oP <- c()
  for(game in n) {oP[[game]] <- Checks[[game]] & (! Captures[[game]])}
  return(oP)
}

isA <- function(y) {
  n <- 1:length(y)
  A <- c()
  for(game in n) {A[[game]] <- Captures[[game]] & Checks[[game]]}
  return(A)
}

isE <- function(y) {
  n <- 1:length(y)
  E <- c()
  for(game in n) {E[[game]] <- ! (Captures[[game]] | Checks[[game]])}
  return(E)
}

oCaptures <- isoX(y)
oChecks <- isoP(y)
Both <- isA(y)
Else <- isE(y)

Empirical Data and the Count Vector

The empirical data is a vector that counts how many times the games existed in each state. The count vector is very similar, except it does not count the last entry in each game. We do this because there is no state that follows the last entry. The count vector is used to build the Markov chain transition matrix.

EmpVector <- function(y) {
EV <- c()
length(y) -> EV[1]
temp2 <- c()
temp3 <- c()
temp4 <- c()
temp5 <- c()
n <- 1:length(y)
for(game in n) {
  sum(oCaptures[[game]], na.rm = TRUE) -> temp2[[game]]
  sum(oChecks[[game]], na.rm = TRUE) -> temp3[[game]]
  sum(Both[[game]], na.rm = TRUE) -> temp4[[game]]
  sum(Else[[game]], na.rm = TRUE) -> temp5[[game]]}
sum(temp2) -> EV[2]
sum(temp3) -> EV[3]
sum(temp4) -> EV[4]
sum(temp5) -> EV[5]
EV <- EV/sum(EV)
return(EV)
}
#I can simplify these functions...
CountVector <- function(y) {
CV <- c()
length(y) -> CV[1]
temp2 <- c()
temp3 <- c()
temp4 <- c()
temp5 <- c()
n <- 1:length(y)
len <- c()
for(game in n) {
  len <- 1:(length(y[[game]])-1)
  sum(oCaptures[[game]][len], na.rm = TRUE) -> temp2[[game]]
  sum(oChecks[[game]][len], na.rm = TRUE) -> temp3[[game]]
  sum(Both[[game]][len], na.rm = TRUE) -> temp4[[game]]
  sum(Else[[game]][len], na.rm = TRUE) -> temp5[[game]]}
sum(temp2) -> CV[2]
sum(temp3) -> CV[3]
sum(temp4) -> CV[4]
sum(temp5) -> CV[5]
return(CV)
}

EV <- EmpVector(y)
CV <- CountVector(y)

The Empirical Data: P(a game at time n≥0 will be in each state)

EV
## [1] 0.01084991 0.17902351 0.03164557 0.01265823 0.76582278

For the purpose of creating a transition matrix I defined a count vector. This defines the number of times the games were in each state before a move. It truncates off the states that occured last in each game. It is not normalized like the empirical data so it can not be seen as a probability distribution.

The Count Vector:

CV
## [1]  12 198  35  13 836

Making the Transition Matrix

P(a game at time (n+1)≥1 will be in state j | the game is in state i at time n)

T <- matrix(1:25, nrow=5, ncol = 5, dimnames = list(States, States))
T[,1] <- 0
T[1,] <- 0
T[1,5] <- 1

MatrixEntry <- function(i, j, count) {
  k <- 0
  n <- 1:length(y)
  for(game in n) {for(entry in 1:(length(i[[game]])-1)) {
    if (i[[game]][entry] & j[[game]][entry+1]) {k=k+1}}}
  return(k/count)
}

###This can be simplified with a loop

T[2,2] = MatrixEntry(oCaptures, oCaptures, CV[2])
T[2,3] = MatrixEntry(oCaptures, oChecks, CV[2])
T[2,4] = MatrixEntry(oCaptures, Both, CV[2])
T[2,5] = MatrixEntry(oCaptures, Else, CV[2])
T[3,2] = MatrixEntry(oChecks, oCaptures, CV[3])
T[3,3] = MatrixEntry(oChecks, oChecks, CV[3])
T[3,4] = MatrixEntry(oChecks, Both, CV[3])
T[3,5] = MatrixEntry(oChecks, Else, CV[3])
T[4,2] = MatrixEntry(Both, oCaptures, CV[4])
T[4,3] = MatrixEntry(Both, oChecks, CV[4])
T[4,4] = MatrixEntry(Both, Both, CV[4])
T[4,5] = MatrixEntry(Both, Else, CV[4])
T[5,2] = MatrixEntry(Else, oCaptures, CV[5])
T[5,3] = MatrixEntry(Else, oChecks, CV[5])
T[5,4] = MatrixEntry(Else, Both, CV[5])
T[5,5] = MatrixEntry(Else, Else, CV[5])
#Quick and dirty
T
##          Initial   oCapture     oCheck        Both      Else
## Initial        0 0.00000000 0.00000000 0.000000000 1.0000000
## oCapture       0 0.44949495 0.02020202 0.030303030 0.5000000
## oCheck         0 0.05714286 0.00000000 0.000000000 0.9428571
## Both           0 0.69230769 0.00000000 0.076923077 0.2307692
## Else           0 0.11722488 0.03708134 0.008373206 0.8373206

Finding the Stationary Vector

SV <- function(Matrix, Labels=TRUE) {
  sv <- c()
  sv <- eigen(t(Matrix))$vectors[,1]
  sv <- sv/sum(sv)
  Out <- sv %*% Matrix
  #This adds back in headers and will throw a bad answer if the function fails.
  if (Labels==TRUE) {return(Out)}
  else {return(sv)}
}
sv <- SV(T,FALSE)
StationaryVector <- SV(T,TRUE)
StationaryVector
##      Initial  oCapture     oCheck       Both      Else
## [1,]       0 0.1838717 0.03229699 0.01302813 0.7708031

This shows that the stationary vector works:

SV(T,TRUE) == SV(T,TRUE) %*% T
##      Initial oCapture oCheck Both Else
## [1,]    TRUE     TRUE   TRUE TRUE TRUE
# This operation happens to work in this case because R has excelent numeric handeling.
# It will not work if Labels = False because it pulls R out of the matrix tools. 
# This code may not work in other languages and possibly with other inputs unless it is rounded.

Stationary Distribution: By transposing the matrix and taking the first eigen vector I get a multiple of the stationary distribution. I then normalize the vector and test it by multiplying it through the original matrix. Because the truncated matrix is normal, we know that our stationary vector is unique.

Analysis

You can see below that the stationary vector is very similar to the empirical data. The most significant difference is in the initial state. The initial state will not show up in the stationary vector because it is transient.

barplot(EV, names.arg = States, ylab = "Probaility", main = "Empirical Data Distribution")

barplot(StationaryVector, main = "Stationary Distribution")

As expected, the initial state was the only transient state in this dataset. This can be seen in this unweighted digraph below. It is also clear that state reaches every other state or itself. Excluding the initial state, this is likely an artifact of the low sample size.

#install.packages("igraph")
library(igraph)
## Warning: package 'igraph' was built under R version 3.3.3
## 
## Attaching package: 'igraph'
## The following objects are masked from 'package:stats':
## 
##     decompose, spectrum
## The following object is masked from 'package:base':
## 
##     union
TGraph <- graph_from_adjacency_matrix(T, weighted=TRUE)
#E(TGraph)$width <- 7*(E(TGraph)$weight)
#as.directed(TGraph, mode = c("mutual", "arbitrary"))
plot(TGraph, main = 'Unweighted Transitions in a Chess Game')

This Markov chain is normal, as several states return to themselves. It has only one stationary class, in addition to the transient initial state. It is asymetric and has a unique stationary distribution. If we took a random walk on this weighted graph the stationary distribution would represent the long run probabilities of being in each state. As shown above, the stationary distribution closely matches the empirical probabilites we found of the game being in each state.

Conclusion

This Markov model is clearly a dramatically simplified model of chess. It strips out the vast majority of the information availible in the raw chess algebra. However, the Markov chain does give convincing answers . . . . .

The Data and Citations

Deep Blue vs Garry Kasparov 1996 and 1997

This is the record of two historic six game chess matches played between Gary Kasperov, the raining world chess champion, and Deep Blue, a super computer developed by IBM. The combination of these two matches has been widely regarded in popular literature as a turning point in the relationship between human and artificial inteligence.

Below is the chess algebra for the first game as a text file in its most common format and then a display of the complete datastructure I convered it into for this project. Notice that some elements including the score and the header have been removed.

Deep Blue–Kasparov
1.e4 c5 2.c3 d5 3.exd5 Qxd5 4.d4 Nf6 5.Nf3 Bg4 6.Be2 e6 7.h3 Bh5 8.0-0 Nc6 9.Be3 cxd4 10.cxd4 Bb4 11.a3 Ba5 12.Nc3 Qd6 13.Nb5 Qe7 14.Ne5 Bxe2 15.Qxe2 0-0 16.Rac1 Rac8 17.Bg5 Bb6 18.Bxf6 gxf6 19.Nc4 Rfd8 20.Nxb6 axb6 21.Rfd1 f5 22.Qe3 Qf6 23.d5 Rxd5 24.Rxd5 exd5 25.b3 Kh8 26.Qxb6 Rg8 27.Qc5 d4 28.Nd6 f4 29.Nxb7 Ne5 30.Qd5 f3 31.g3 Nd3 32.Rc7 Re8 33.Nd6 Re1+ 34.Kh2 Nxf2 35.Nxf7+ Kg7 36.Ng5+ Kh6 37.Rxh7+ 1–0

Works Cited

All chess algebra was taken from Wikipedia’s account of the games.

https://en.wikipedia.org/wiki/Deep_Blue_versus_Garry_Kasparov

The conventions for interpreting the algebra are widely standerdized but I used the World Chess Federation’s (FIDE) Handbook, Section E, Laws of Chess.

http://www.fide.com/component/handbook/

The Data

This is the cleaned dataset as nested vectors showing all twelve games for reference.

y
## [[1]]
##  [1] "1.e4"     "c5"       "2.c3"     "d5"       "3.exd5"   "Qxd5"    
##  [7] "4.d4"     "Nf6"      "5.Nf3"    "Bg4"      "6.Be2"    "e6"      
## [13] "7.h3"     "Bh5"      "8.0-0"    "Nc6"      "9.Be3"    "cxd4"    
## [19] "10.cxd4"  "Bb4"      "11.a3"    "Ba5"      "12.Nc3"   "Qd6"     
## [25] "13.Nb5"   "Qe7"      "14.Ne5"   "Bxe2"     "15.Qxe2"  "0-0"     
## [31] "16.Rac1"  "Rac8"     "17.Bg5"   "Bb6"      "18.Bxf6"  "gxf6"    
## [37] "19.Nc4"   "Rfd8"     "20.Nxb6"  "axb6"     "21.Rfd1"  "f5"      
## [43] "22.Qe3"   "Qf6"      "23.d5"    "Rxd5"     "24.Rxd5"  "exd5"    
## [49] "25.b3"    "Kh8"      "26.Qxb6"  "Rg8"      "27.Qc5"   "d4"      
## [55] "28.Nd6"   "f4"       "29.Nxb7"  "Ne5"      "30.Qd5"   "f3"      
## [61] "31.g3"    "Nd3"      "32.Rc7"   "Re8"      "33.Nd6"   "Re1+"    
## [67] "34.Kh2"   "Nxf2"     "35.Nxf7+" "Kg7"      "36.Ng5+"  "Kh6"     
## [73] "37.Rxh7+"
## 
## [[2]]
##   [1] "1.Nf3"   "d5"      "2.d4"    "e6"      "3.g3"    "c5"      "4.Bg2"  
##   [8] "Nc6"     "5.0-0"   "Nf6"     "6.c4"    "dxc4"    "7.Ne5"   "Bd7"    
##  [15] "8.Na3"   "cxd4"    "9.Naxc4" "Bc5"     "10.Qb3"  "0-0"     "11.Qxb7"
##  [22] "Nxe5"    "12.Nxe5" "Rb8"     "13.Qf3"  "Bd6"     "14.Nc6"  "Bxc6"   
##  [29] "15.Qxc6" "e5"      "16.Rb1"  "Rb6"     "17.Qa4"  "Qb8"     "18.Bg5" 
##  [36] "Be7"     "19.b4"   "Bxb4"    "20.Bxf6" "gxf6"    "21.Qd7"  "Qc8"    
##  [43] "22.Qxa7" "Rb8"     "23.Qa4"  "Bc3"     "24.Rxb8" "Qxb8"    "25.Be4" 
##  [50] "Qc7"     "26.Qa6"  "Kg7"     "27.Qd3"  "Rb8"     "28.Bxh7" "Rb2"    
##  [57] "29.Be4"  "Rxa2"    "30.h4"   "Qc8"     "31.Qf3"  "Ra1"     "32.Rxa1"
##  [64] "Bxa1"    "33.Qh5"  "Qh8"     "34.Qg4+" "Kf8"     "35.Qc8+" "Kg7"    
##  [71] "36.Qg4+" "Kf8"     "37.Bd5"  "Ke7"     "38.Bc6"  "Kf8"     "39.Bd5" 
##  [78] "Ke7"     "40.Qf3"  "Bc3"     "41.Bc4"  "Qc8"     "42.Qd5"  "Qe6"    
##  [85] "43.Qb5"  "Qd7"     "44.Qc5+" "Qd6"     "45.Qa7+" "Qd7"     "46.Qa8" 
##  [92] "Qc7"     "47.Qa3+" "Qd6"     "48.Qa2"  "f5"      "49.Bxf7" "e4"     
##  [99] "50.Bh5"  "Qf6"     "51.Qa3+" "Kd7"     "52.Qa7+" "Kd8"     "53.Qb8+"
## [106] "Kd7"     "54.Be8+" "Ke7"     "55.Bb5"  "Bd2"     "56.Qc7+" "Kf8"    
## [113] "57.Bc4"  "Bc3"     "58.Kg2"  "Be1"     "59.Kf1"  "Bc3"     "60.f4"  
## [120] "exf3"    "61.exf3" "Bd2"     "62.f4"   "Ke8"     "63.Qc8+" "Ke7"    
## [127] "64.Qc5+" "Kd8"     "65.Bd3"  "Be3"     "66.Qxf5" "Qc6"     "67.Qf8+"
## [134] "Kc7"     "68.Qe7+" "Kc8"     "69.Bf5+" "Kb8"     "70.Qd8+" "Kb7"    
## [141] "71.Qd7+" "Qxd7"    "72.Bxd7" "Kc7"     "73.Bb5" 
## 
## [[3]]
##  [1] "1.e4"    "c5"      "2.c3"    "d5"      "3.exd5"  "Qxd5"    "4.d4"   
##  [8] "Nf6"     "5.Nf3"   "Bg4"     "6.Be2"   "e6"      "7.0-0"   "Nc6"    
## [15] "8.Be3"   "cxd4"    "9.cxd4"  "Bb4"     "10.a3"   "Ba5"     "11.Nc3" 
## [22] "Qd6"     "12.Ne5"  "Bxe2"    "13.Qxe2" "Bxc3"    "14.bxc3" "Nxe5"   
## [29] "15.Bf4"  "Nf3+"    "16.Qxf3" "Qd5"     "17.Qd3"  "Rc8"     "18.Rfc1"
## [36] "Qc4"     "19.Qxc4" "Rxc4"    "20.Rcb1" "b6"      "21.Bb8"  "Ra4"    
## [43] "22.Rb4"  "Ra5"     "23.Rc4"  "0-0"     "24.Bd6"  "Ra8"     "25.Rc6" 
## [50] "b5"      "26.Kf1"  "Ra4"     "27.Rb1"  "a6"      "28.Ke2"  "h5"     
## [57] "29.Kd3"  "Rd8"     "30.Be7"  "Rd7"     "31.Bxf6" "gxf6"    "32.Rb3" 
## [64] "Kg7"     "33.Ke3"  "e5"      "34.g3"   "exd4+"   "35.cxd4" "Re7+"   
## [71] "36.Kf3"  "Rd7"     "37.Rd3"  "Raxd4"   "38.Rxd4" "Rxd4"    "39.Rxa6"
## [78] "b4"     
## 
## [[4]]
##   [1] "1.Nf3"    "d5"       "2.d4"     "c6"       "3.c4"     "e6"      
##   [7] "4.Nbd2"   "Nf6"      "5.e3"     "Nbd7"     "6.Bd3"    "Bd6"     
##  [13] "7.e4"     "dxe4"     "8.Nxe4"   "Nxe4"     "9.Bxe4"   "0-0"     
##  [19] "10.0-0"   "h6"       "11.Bc2"   "e5"       "12.Re1"   "exd4"    
##  [25] "13.Qxd4"  "Bc5"      "14.Qc3"   "a5"       "15.a3"    "Nf6"     
##  [31] "16.Be3"   "Bxe3"     "17.Rxe3"  "Bg4"      "18.Ne5"   "Re8"     
##  [37] "19.Rae1"  "Be6"      "20.f4"    "Qc8"      "21.h3"    "b5"      
##  [43] "22.f5"    "Bxc4"     "23.Nxc4"  "bxc4"     "24.Rxe8+" "Nxe8"    
##  [49] "25.Re4"   "Nf6"      "26.Rxc4"  "Nd5"      "27.Qe5"   "Qd7"     
##  [55] "28.Rg4"   "f6"       "29.Qd4"   "Kh7"      "30.Re4"   "Rd8"     
##  [61] "31.Kh1"   "Qc7"      "32.Qf2"   "Qb8"      "33.Ba4"   "c5"      
##  [67] "34.Bc6"   "c4"       "35.Rxc4"  "Nb4"      "36.Bf3"   "Nd3"     
##  [73] "37.Qh4"   "Qxb2"     "38.Qg3"   "Qxa3"     "39.Rc7"   "Qf8"     
##  [79] "40.Ra7"   "Ne5"      "41.Rxa5"  "Qf7"      "42.Rxe5"  "fxe5"    
##  [85] "43.Qxe5"  "Re8"      "44.Qf4"   "Qf6"      "45.Bh5"   "Rf8"     
##  [91] "46.Bg6+"  "Kh8"      "47.Qc7"   "Qd4"      "48.Kh2"   "Ra8"     
##  [97] "49.Bh5"   "Qf6"      "50.Bg6"   "Rg8"     
## 
## [[5]]
##  [1] "1.e4"     "e5"       "2.Nf3"    "Nf6"      "3.Nc3"    "Nc6"     
##  [7] "4.d4"     "exd4"     "5.Nxd4"   "Bb4"      "6.Nxc6"   "bxc6"    
## [13] "7.Bd3"    "d5"       "8.exd5"   "cxd5"     "9.0-0"    "0-0"     
## [19] "10.Bg5"   "c6"       "11.Qf3"   "Be7"      "12.Rae1"  "Re8"     
## [25] "13.Ne2"   "h6"       "14.Bf4"   "Bd6"      "15.Nd4"   "Bg4"     
## [31] "16.Qg3"   "Bxf4"     "17.Qxf4"  "Qb6"      "18.c4"    "Bd7"     
## [37] "19.cxd5"  "cxd5"     "20.Rxe8+" "Rxe8"     "21.Qd2"   "Ne4"     
## [43] "22.Bxe4"  "dxe4"     "23.b3"    "Rd8"      "24.Qc3"   "f5"      
## [49] "25.Rd1"   "Be6"      "26.Qe3"   "Bf7"      "27.Qc3"   "f4"      
## [55] "28.Rd2"   "Qf6"      "29.g3"    "Rd5"      "30.a3"    "Kh7"     
## [61] "31.Kg2"   "Qe5"      "32.f3"    "e3"       "33.Rd3"   "e2"      
## [67] "34.gxf4"  "e1=Q"     "35.fxe5"  "Qxc3"     "36.Rxc3"  "Rxd4"    
## [73] "37.b4"    "Bc4"      "38.Kf2"   "g5"       "39.Re3"   "Be6"     
## [79] "40.Rc3"   "Bc4"      "41.Re3"   "Rd2+"     "42.Ke1"   "Rd3"     
## [85] "43.Kf2"   "Kg6"      "44.Rxd3"  "Bxd3"     "45.Ke3"   "Bc2"     
## [91] "46.Kd4"   "Kf5"      "47.Kd5"   "h5"      
## 
## [[6]]
##  [1] "1.Nf3"   "d5"      "2.d4"    "c6"      "3.c4"    "e6"      "4.Nbd2" 
##  [8] "Nf6"     "5.e3"    "c5"      "6.b3"    "Nc6"     "7.Bb2"   "cxd4"   
## [15] "8.exd4"  "Be7"     "9.Rc1"   "0-0"     "10.Bd3"  "Bd7"     "11.0-0" 
## [22] "Nh5"     "12.Re1"  "Nf4"     "13.Bb1"  "Bd6"     "14.g3"   "Ng6"    
## [29] "15.Ne5"  "Rc8"     "16.Nxd7" "Qxd7"    "17.Nf3"  "Bb4"     "18.Re3" 
## [36] "Rfd8"    "19.h4"   "Nge7"    "20.a3"   "Ba5"     "21.b4"   "Bc7"    
## [43] "22.c5"   "Re8"     "23.Qd3"  "g6"      "24.Re2"  "Nf5"     "25.Bc3" 
## [50] "h5"      "26.b5"   "Nce7"    "27.Bd2"  "Kg7"     "28.a4"   "Ra8"    
## [57] "29.a5"   "a6"      "30.b6"   "Bb8"     "31.Bc2"  "Nc6"     "32.Ba4" 
## [64] "Re7"     "33.Bc3"  "Ne5"     "34.dxe5" "Qxa4"    "35.Nd4"  "Nxd4"   
## [71] "36.Qxd4" "Qd7"     "37.Bd2"  "Re8"     "38.Bg5"  "Rc8"     "39.Bf6+"
## [78] "Kh7"     "40.c6"   "bxc6"    "41.Qc5"  "Kh6"     "42.Rb2"  "Qb7"    
## [85] "43.Rb4" 
## 
## [[7]]
##  [1] "1.Nf3"    "d5"       "2.g3"     "Bg4"      "3.b3"     "Nd7"     
##  [7] "4.Bb2"    "e6"       "5.Bg2"    "Ngf6"     "6.0-0"    "c6"      
## [13] "7.d3"     "Bd6"      "8.Nbd2"   "0-0"      "9.h3"     "Bh5"     
## [19] "10.e3"    "h6"       "11.Qe1"   "Qa5"      "12.a3"    "Bc7"     
## [25] "13.Nh4"   "g5"       "14.Nhf3"  "e5"       "15.e4"    "Rfe8"    
## [31] "16.Nh2"   "Qb6"      "17.Qc1"   "a5"       "18.Re1"   "Bd6"     
## [37] "19.Ndf1"  "dxe4"     "20.dxe4"  "Bc5"      "21.Ne3"   "Rad8"    
## [43] "22.Nhf1"  "g4"       "23.hxg4"  "Nxg4"     "24.f3"    "Nxe3"    
## [49] "25.Nxe3"  "Be7"      "26.Kh1"   "Bg5"      "27.Re2"   "a4"      
## [55] "28.b4"    "f5"       "29.exf5"  "e4"       "30.f4"    "Bxe2"    
## [61] "31.fxg5"  "Ne5"      "32.g6"    "Bf3"      "33.Bc3"   "Qb5"     
## [67] "34.Qf1"   "Qxf1+"    "35.Rxf1"  "h5"       "36.Kg1"   "Kf8"     
## [73] "37.Bh3"   "b5"       "38.Kf2"   "Kg7"      "39.g4"    "Kh6"     
## [79] "40.Rg1"   "hxg4"     "41.Bxg4"  "Bxg4"     "42.Nxg4+" "Nxg4+"   
## [85] "43.Rxg4"  "Rd5"      "44.f6"    "Rd1"      "45.g7"   
## 
## [[8]]
##  [1] "1.e4"    "e5"      "2.Nf3"   "Nc6"     "3.Bb5"   "a6"      "4.Ba4"  
##  [8] "Nf6"     "5.0-0"   "Be7"     "6.Re1"   "b5"      "7.Bb3"   "d6"     
## [15] "8.c3"    "0-0"     "9.h3"    "h6"      "10.d4"   "Re8"     "11.Nbd2"
## [22] "Bf8"     "12.Nf1"  "Bd7"     "13.Ng3"  "Na5"     "14.Bc2"  "c5"     
## [29] "15.b3"   "Nc6"     "16.d5"   "Ne7"     "17.Be3"  "Ng6"     "18.Qd2" 
## [36] "Nh7"     "19.a4"   "Nh4"     "20.Nxh4" "Qxh4"    "21.Qe2"  "Qd8"    
## [43] "22.b4"   "Qc7"     "23.Rec1" "c4"      "24.Ra3"  "Rec8"    "25.Rca1"
## [50] "Qd8"     "26.f4"   "Nf6"     "27.fxe5" "dxe5"    "28.Qf1"  "Ne8"    
## [57] "29.Qf2"  "Nd6"     "30.Bb6"  "Qe8"     "31.R3a2" "Be7"     "32.Bc5" 
## [64] "Bf8"     "33.Nf5"  "Bxf5"    "34.exf5" "f6"      "35.Bxd6" "Bxd6"   
## [71] "36.axb5" "axb5"    "37.Be4"  "Rxa2"    "38.Qxa2" "Qd7"     "39.Qa7" 
## [78] "Rc7"     "40.Qb6"  "Rb7"     "41.Ra8+" "Kf7"     "42.Qa6"  "Qc7"    
## [85] "43.Qc6"  "Qb6+"    "44.Kf1"  "Rb8"     "45.Ra6" 
## 
## [[9]]
##  [1] "1.d3"     "e5"       "2.Nf3"    "Nc6"      "3.c4"     "Nf6"     
##  [7] "4.a3"     "d6"       "5.Nc3"    "Be7"      "6.g3"     "0-0"     
## [13] "7.Bg2"    "Be6"      "8.0-0"    "Qd7"      "9.Ng5"    "Bf5"     
## [19] "10.e4"    "Bg4"      "11.f3"    "Bh5"      "12.Nh3"   "Nd4"     
## [25] "13.Nf2"   "h6"       "14.Be3"   "c5"       "15.b4"    "b6"      
## [31] "16.Rb1"   "Kh8"      "17.Rb2"   "a6"       "18.bxc5"  "bxc5"    
## [37] "19.Bh3"   "Qc7"      "20.Bg4"   "Bg6"      "21.f4"    "exf4"    
## [43] "22.gxf4"  "Qa5"      "23.Bd2"   "Qxa3"     "24.Ra2"   "Qb3"     
## [49] "25.f5"    "Qxd1"     "26.Bxd1"  "Bh7"      "27.Nh3"   "Rfb8"    
## [55] "28.Nf4"   "Bd8"      "29.Nfd5"  "Nc6"      "30.Bf4"   "Ne5"     
## [61] "31.Ba4"   "Nxd5"     "32.Nxd5"  "a5"       "33.Bb5"   "Ra7"     
## [67] "34.Kg2"   "g5"       "35.Bxe5+" "dxe5"     "36.f6"    "Bg6"     
## [73] "37.h4"    "gxh4"     "38.Kh3"   "Kg8"      "39.Kxh4"  "Kh7"     
## [79] "40.Kg4"   "Bc7"      "41.Nxc7"  "Rxc7"     "42.Rxa5"  "Rd8"     
## [85] "43.Rf3"   "Kh8"      "44.Kh4"   "Kg8"      "45.Ra3"   "Kh8"     
## [91] "46.Ra6"   "Kh7"      "47.Ra3"   "Kh8"      "48.Ra6"  
## 
## [[10]]
##   [1] "1.e4"     "c6"       "2.d4"     "d6"       "3.Nf3"    "Nf6"     
##   [7] "4.Nc3"    "Bg4"      "5.h3"     "Bh5"      "6.Bd3"    "e6"      
##  [13] "7.Qe2"    "d5"       "8.Bg5"    "Be7"      "9.e5"     "Nfd7"    
##  [19] "10.Bxe7"  "Qxe7"     "11.g4"    "Bg6"      "12.Bxg6"  "hxg6"    
##  [25] "13.h4"    "Na6"      "14.0-0-0" "0-0-0"    "15.Rdg1"  "Nc7"     
##  [31] "16.Kb1"   "f6"       "17.exf6"  "Qxf6"     "18.Rg3"   "Rde8"    
##  [37] "19.Re1"   "Rhf8"     "20.Nd1"   "e5"       "21.dxe5"  "Qf4"     
##  [43] "22.a3"    "Ne6"      "23.Nc3"   "Ndc5"     "24.b4"    "Nd7"     
##  [49] "25.Qd3"   "Qf7"      "26.b5"    "Ndc5"     "27.Qe3"   "Qf4"     
##  [55] "28.bxc6"  "bxc6"     "29.Rd1"   "Kc7"      "30.Ka1"   "Qxe3"    
##  [61] "31.fxe3"  "Rf7"      "32.Rh3"   "Ref8"     "33.Nd4"   "Rf2"     
##  [67] "34.Rb1"   "Rg2"      "35.Nce2"  "Rxg4"     "36.Nxe6+" "Nxe6"    
##  [73] "37.Nd4"   "Nxd4"     "38.exd4"  "Rxd4"     "39.Rg1"   "Rc4"     
##  [79] "40.Rxg6"  "Rxc2"     "41.Rxg7+" "Kb6"      "42.Rb3+"  "Kc5"     
##  [85] "43.Rxa7"  "Rf1+"     "44.Rb1"   "Rff2"     "45.Rb4"   "Rc1+"    
##  [91] "46.Rb1"   "Rcc2"     "47.Rb4"   "Rc1+"     "48.Rb1"   "Rxb1+"   
##  [97] "49.Kxb1"  "Re2"      "50.Re7"   "Rh2"      "51.Rh7"   "Kc4"     
## [103] "52.Rc7"   "c5"       "53.e6"    "Rxh4"     "54.e7"    "Re4"     
## [109] "55.a4"    "Kb3"      "56.Kc1"  
## 
## [[11]]
##  [1] "1.Nf3"    "d5"       "2.g3"     "Bg4"      "3.Bg2"    "Nd7"     
##  [7] "4.h3"     "Bxf3"     "5.Bxf3"   "c6"       "6.d3"     "e6"      
## [13] "7.e4"     "Ne5"      "8.Bg2"    "dxe4"     "9.Bxe4"   "Nf6"     
## [19] "10.Bg2"   "Bb4+"     "11.Nd2"   "h5"       "12.Qe2"   "Qc7"     
## [25] "13.c3"    "Be7"      "14.d4"    "Ng6"      "15.h4"    "e5"      
## [31] "16.Nf3"   "exd4"     "17.Nxd4"  "0-0-0"    "18.Bg5"   "Ng4"     
## [37] "19.0-0-0" "Rhe8"     "20.Qc2"   "Kb8"      "21.Kb1"   "Bxg5"    
## [43] "22.hxg5"  "N6e5"     "23.Rhe1"  "c5"       "24.Nf3"   "Rxd1+"   
## [49] "25.Rxd1"  "Nc4"      "26.Qa4"   "Rd8"      "27.Re1"   "Nb6"     
## [55] "28.Qc2"   "Qd6"      "29.c4"    "Qg6"      "30.Qxg6"  "fxg6"    
## [61] "31.b3"    "Nxf2"     "32.Re6"   "Kc7"      "33.Rxg6"  "Rd7"     
## [67] "34.Nh4"   "Nc8"      "35.Bd5"   "Nd6"      "36.Re6"   "Nb5"     
## [73] "37.cxb5"  "Rxd5"     "38.Rg6"   "Rd7"      "39.Nf5"   "Ne4"     
## [79] "40.Nxg7"  "Rd1+"     "41.Kc2"   "Rd2+"     "42.Kc1"   "Rxa2"    
## [85] "43.Nxh5"  "Nd2"      "44.Nf4"   "Nxb3+"    "45.Kb1"   "Rd2"     
## [91] "46.Re6"   "c4"       "47.Re3"   "Kb6"      "48.g6"    "Kxb5"    
## [97] "49.g7"    "Kb4"     
## 
## [[12]]
##  [1] "1.e4"    "c6"      "2.d4"    "d5"      "3.Nc3"   "dxe4"    "4.Nxe4" 
##  [8] "Nd7"     "5.Ng5"   "Ngf6"    "6.Bd3"   "e6"      "7.N1f3"  "h6"     
## [15] "8.Nxe6"  "Qe7"     "9.0-0"   "fxe6"    "10.Bg6+" "Kd8"     "11.Bf4" 
## [22] "b5"      "12.a4"   "Bb7"     "13.Re1"  "Nd5"     "14.Bg3"  "Kc8"    
## [29] "15.axb5" "cxb5"    "16.Qd3"  "Bc6"     "17.Bf5"  "exf5"    "18.Rxe7"
## [36] "Bxe7"    "19.c4"