# 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

- `board`: the current position
- `turn`: 1 if it is white’s turn, -1 if it is black’s turn
- `history`: the previous moves played (in a primitive style)
- `fen_history`: the FEN representation of the previous moves

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

- the game being played
- the piece label (p for pawns, N for knights, B for bishops, R for rooks, Q for queens, K for kings)
- the initial square of the piece to be moved
- the final square

    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:

- `style = 1` is the default option: unicode encoding is used
- `style = 2` plots pieces with their labels instead of the unicode. As unicode may yield an error on some platforms, here we use this option

    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.

### Legal moves

All legal moves in a given position can be listed using the function `legalmoves`

    legalmoves(g2)

    ##  [1] "pa2a3" "pa2a4" "Bb5e2" "Bb5d3" "Bb5c4" "Bb5a6" "Bb5a4" "Bb5c6" "pb2b3"
    ## [10] "pb2b4" "Nb1a3" "Nb1c3" "pc2c3" "pc2c4" "pd2d3" "pd2d4" "Qd1e1" "Qd1e2"
    ## [19] "Nf3e5" "Nf3d4" "Nf3g5" "Nf3h4" "Nf3e1" "Rf1e1" "pg2g3" "pg2g4" "Kg1h1"
    ## [28] "ph2h3" "ph2h4"

### 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

- https://en.wikipedia.org/wiki/Minimax
- https://www.r-bloggers.com/2022/07/programming-a-simple-minimax-chess-engine-in-r/

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)