Chess: Forsyth-Edwards Notation

:: programming, racket, artificial intelligence, lisp, scheme

FEN - Forsyth-Edwards Notation

Part of the How to Program a Chess Engine in Lisp series.

Now that we have pieces and a board, we need a convenient way of setting pieces on the board in specific positions. We’ll use this, not only for the initial position of a game, but also to configure a board with specific game scenarios for testing and debugging.

The standard way to do this is to use FEN, or Forsyth-Edwards Notation: [Wikipedia] [Chess Programming Wiki]

Here is the source for fen.rkt

FEN specifies more than just the placement of pieces on the board; however, for now, we’ll just implement the portion of FEN that specifies piece placement, and add the additional functionality later, when we need it.

The initial configuration of pieces for the start of a game with white at the bottom and black at the top is:

1
(define initial-fen-placement "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR")

Lower case letters indicate black pieces. Upper case letters indicate white pieces. Numbers represent the number of blank squares.

We can now setup an initial game position, and print the board as follows:

1
(print-board (fen-placement->board initial-fen-placement))
---------------------------------
| r | n | b | q | k | b | n | r |  8
---------------------------------
| p | p | p | p | p | p | p | p |  7
---------------------------------
|   |   |   |   |   |   |   |   |  6
---------------------------------
|   |   |   |   |   |   |   |   |  5
---------------------------------
|   |   |   |   |   |   |   |   |  4
---------------------------------
|   |   |   |   |   |   |   |   |  3
---------------------------------
| P | P | P | P | P | P | P | P |  2
---------------------------------
| R | N | B | Q | K | B | N | R |  1
---------------------------------
| a | b | c | d | e | f | g | h |

Or, maybe we’re debugging a problem with identifying checkmate, so we setup the following board:

1
(print-board (fen-placement->board "2K3r1/8/5n2/n7/8/8/7b/8"))
---------------------------------
|   |   | K |   |   |   | r |   |  8
---------------------------------
|   |   |   |   |   |   |   |   |  7
---------------------------------
|   |   |   |   |   | n |   |   |  6
---------------------------------
| n |   |   |   |   |   |   |   |  5
---------------------------------
|   |   |   |   |   |   |   |   |  4
---------------------------------
|   |   |   |   |   |   |   |   |  3
---------------------------------
|   |   |   |   |   |   |   | b |  2
---------------------------------
|   |   |   |   |   |   |   |   |  1
---------------------------------
| a | b | c | d | e | f | g | h |

It will also be useful to be able to produce a FEN placement string from a board. Naturally, there is an inverse relationship as shown in one of the tests:

1
2
(check-equal? (board->fen-placement (fen-placement->board initial-fen-placement))
              initial-fen-placement)