chess2plyrs

chess2plyrs is an R package which allows to create a chess game and add moves, verify the status of the game and list legal moves, as well as read and write FENs. It is also possible to plot the current board position. A simple chess engine based on minimax is also implemented.

library(chess2plyrs)

Initialise a game

A new game can be created with the newgame function:

g1 <- newgame()
g1
## $board
##   a    b    c    d    e    f    g    h   
## 8 "Rb" "Nb" "Bb" "Qb" "Kb" "Bb" "Nb" "Rb"
## 7 "pb" "pb" "pb" "pb" "pb" "pb" "pb" "pb"
## 6 ""   ""   ""   ""   ""   ""   ""   ""  
## 5 ""   ""   ""   ""   ""   ""   ""   ""  
## 4 ""   ""   ""   ""   ""   ""   ""   ""  
## 3 ""   ""   ""   ""   ""   ""   ""   ""  
## 2 "pw" "pw" "pw" "pw" "pw" "pw" "pw" "pw"
## 1 "Rw" "Nw" "Bw" "Qw" "Kw" "Bw" "Nw" "Rw"
## 
## $turn
## [1] 1
## 
## $history
## NULL
## 
## $fen_history
## [1] "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w"

We can see that the object we create is a lists which contains

We can add one move using the chess_move function, which takes in input:

chess_move(game = g1,
            piece = "p",
            initialposition = "e2",
            finalposition = "e4")
## $board
##   a    b    c    d    e    f    g    h   
## 8 "Rb" "Nb" "Bb" "Qb" "Kb" "Bb" "Nb" "Rb"
## 7 "pb" "pb" "pb" "pb" "pb" "pb" "pb" "pb"
## 6 ""   ""   ""   ""   ""   ""   ""   ""  
## 5 ""   ""   ""   ""   ""   ""   ""   ""  
## 4 ""   ""   ""   ""   "pw" ""   ""   ""  
## 3 ""   ""   ""   ""   ""   ""   ""   ""  
## 2 "pw" "pw" "pw" "pw" ""   "pw" "pw" "pw"
## 1 "Rw" "Nw" "Bw" "Qw" "Kw" "Bw" "Nw" "Rw"
## 
## $turn
## [1] -1
## 
## $history
## [1] "pe2-e4"
## 
## $fen_history
## [1] "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w"  
## [2] "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b"

We can also make use of the pipe operator for a smoother insertion of the moves:

g2 <- newgame() |>
  chess_move("p", "e2", "e4")  |>
  chess_move("p", "e7", "e5")  |>
  chess_move("N", "g1", "f3")  |>
  chess_move("N", "b8", "c6")  |>
  chess_move("B", "f1", "b5")  |>
  chess_move("N", "g8", "f6")  |>
  chess_move("K", "e1", "0-0") |>
  chess_move("N", "f6", "e4") 

If we try to add an illegal move, a note tells us that the move is not legal and the action is not performed:

x <- newgame() |>
  chess_move("p", "e2", "d5") # illegal move
## Move not valid

Chess plotting

First, we can plot the current board with the function chessplot. The style option allows for different piece styles:

chessplot(g2, style = 2)

Score list

We can get the moves list in scientific notation using the moves_scoresheet function

moves_scoresheet(g2)
##   n white black
## 1 1    e4    e5
## 2 2   Nf3   Nc6
## 3 3   Bb5   Nf6
## 4 4   0-0  Nxe4

Game result

The function game_result tells whether the game is still ongoing or if there is a checkmate or stalemate.

game_result(g2)
## There are still legal moves available, the game is ongoing
## To move: white
## [1] 0

We can see that in the current position there are still legal moves, hence the game is not finished.

Takeback

The function takeback allows to remove the last move played. It can also be used sequentially.

takeback(g2)
## $board
##   a    b    c    d    e    f    g    h   
## 8 "Rb" ""   "Bb" "Qb" "Kb" "Bb" ""   "Rb"
## 7 "pb" "pb" "pb" "pb" ""   "pb" "pb" "pb"
## 6 ""   ""   "Nb" ""   ""   "Nb" ""   ""  
## 5 ""   "Bw" ""   ""   "pb" ""   ""   ""  
## 4 ""   ""   ""   ""   "pw" ""   ""   ""  
## 3 ""   ""   ""   ""   ""   "Nw" ""   ""  
## 2 "pw" "pw" "pw" "pw" ""   "pw" "pw" "pw"
## 1 "Rw" "Nw" "Bw" "Qw" ""   "Rw" "Kw" ""  
## 
## $turn
## [1] -1
## 
## $history
## [1] "pe2-e4"  "pe7-e5"  "Ng1-f3"  "Nb8-c6"  "Bf1-b5"  "Ng8-f6"  "Ke1_0-0"
## 
## $fen_history
## [1] "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w"            
## [2] "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b"          
## [3] "rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR w"        
## [4] "rnbqkbnr/pppp1ppp/8/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R b"      
## [5] "r1bqkbnr/pppp1ppp/2n5/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w"    
## [6] "r1bqkbnr/pppp1ppp/2n5/1B2p3/4P3/5N2/PPPP1PPP/RNBQK2R b"   
## [7] "r1bqkb1r/pppp1ppp/2n2n2/1B2p3/4P3/5N2/PPPP1PPP/RNBQK2R w" 
## [8] "r1bqkb1r/pppp1ppp/2n2n2/1B2p3/4P3/5N2/PPPP1PPP/RNBQ1RK1 b"

Engine

Along with a simple random mover engine, which can be called using the function random_mover, a slightly more sophisticated engine which uses minimax and alpha-beta pruning is present in this package. For more information have a look at

We can set a simple position and see the move chosen by each engine with different depths:

ck4 <- newgame() |>

  chess_move("N", "b1", "a3") |>
  chess_move("p", "e7", "e6") |>

  chess_move("p", "f2", "f4") |>
  chess_move("p", "a7", "a6") |>
  chess_move("p", "h2", "h3") |>
  chess_move("p", "h7", "h6") |>
  chess_move("N", "a3", "b5")

chessplot(ck4, style = 2)

You can see that black is to move and has a mate starting with Qh4+ (g3, Qxg3#). You can verify that with depth equal to 3 the engine indeed selects that as the move of choice, while at lower depth it prefers to take the Knight in b5.

#engine2(ck4, 1) # "pa6b5" is the chosen move (5 seconds needed)
#engine2(ck4, 2) # "pa6b5" is the chosen move (2/3 minutes needed)
#engine2(ck4, 3) # "Qd8h4" is the chosen move (it takes some minutes to find it)