Converting a FEN Chess Position Into a PGN Move



Original Source Here

Converting a FEN Chess Position Into a PGN Move

A few months ago I was experimenting with React and built this failed chessboard while learning Flux. Basically this was just a chess board intended to connect to a PHP Chess server.

At that time, Flux seemed as an option that would help give structure to my frontend code, however Redux ended up emerging as the leading trend in the React ecosystem. So after a few more side-projects I learned some Redux, which in my humble opinion might be slightly better than Flux.

I feel a bit ashamed to confess I knew little about the FEN format by then.

It seemed to me that playing around with PGN moves on the frontend side of things would make sense, and as a result I wrote something like a pseudo-PGN validation in a JavaScript file which turned out to be pointless.

This code looks at least weird, not to say horrible, to my present self even though I guess — I want to believe — this is what an experiment is about.

Isn’t it?

The funny thing is that it’s much more easy to build the FEN representation of a chess position on the frontend side, than it is to represent such position in terms of PGN moves — as I originally did.

I came to the conclusion that the simplest thing to do for a JavaScript chess board to play a chess move is to send two FEN strings to a chess server for further validation and processing.

Of course, the former is to represent an initial position and the latter the target position.

Therefore, I implemented the playFen() method in the PHP Chess library and added it to PHP Chess server so that web clients can send chess commands as described next.

const ws = new WebSocket('ws://127.0.0.1:8080');
ws.onmessage = (res) => { console.log(res.data) };
ws.send('/start pvt');
ws.send('/playfen "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq -" "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3"');

The JavaScript code above should be self-explanatory, but let me show you an overview of the commands available which is displayed when the PHP Ratchet WebSocket server is started.

$ php cli/ws-server.php 
Welcome to PHP Chess Server
Commands available:
/ascii Prints the ASCII representation of the game.
/captures Gets the pieces captured by both players.
/fen Prints the FEN string representation of the game.
/history The current game's history.
/ischeck Finds out if the game is in check.
/ismate Finds out if the game is over.
/piece {"position":"square"} Gets a piece by its position on the board. The "position" parameter is mandatory.
/pieces {"color":["w","b"]} Gets the pieces on the board by color. The "color" parameter is mandatory.
/play {"color":["w","b"],"pgn":"move"} Plays a chess move on the board. All parameters are mandatory.
/playfen {"from":"FEN","to":"FEN"} Plays a chess move on the board. All parameters are mandatory.
/quit Quits a game.
/start {"mode":["pvt"],"color":["w","b"]} Starts a new game. The "color" parameter is not required in pvt (player vs themselves) mode.
/status The current game status.
Listening to commands...
New connection (92)

Here is how the /playfen command is called in the web dev console.

Figure 1. White plays e4

And below are attached two PHP unit tests that I wrote when TDDing the playFen() method. Hopefully these will provide insight on how to convert a FEN chess position into a PGN move from a server-side perspective.

namespace Chess\Tests\Unit\Fen;use Chess\FenPgn;
use Chess\PGN\Symbol;
use Chess\Tests\AbstractUnitTestCase;
class FenPgnTest extends AbstractUnitTestCase
{
/**
* @test
*/
public function e4()
{
$pgn = (new FenPgn(
'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq -',
'rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3'
))->create();
$expected = [
Symbol::WHITE => 'e4',
];
$this->assertEquals($expected, $pgn);
}
/**
* @test
*/
public function Nf3()
{
$pgn = (new FenPgn(
'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq -',
'rnbqkbnr/pppppppp/8/8/8/5N2/PPPPPPPP/RNBQKB1R b KQkq -'
))->create();
$expected = [
Symbol::WHITE => 'Nf3',
];
$this->assertEquals($expected, $pgn);
}
}

Finally, the following sequence of chess moves:

use Chess\Game;

$game = new Game();

$game->play('w', 'e4');
$game->play('b', 'd5');
$game->play('w', 'exd5');
$game->play('b', 'Qxd5');
$game->playFen(
'rnb1kbnr/ppp1pppp/8/3q4/8/8/PPPP1PPP/RNBQKBNR w KQkq -',
'rnb1kbnr/ppp1pppp/8/3q4/8/2N5/PPPP1PPP/R1BQKBNR b KQkq -'
);

echo $game->ascii();

Generates this output:

r  n  b  .  k  b  n  r
p p p . p p p p
. . . . . . . .
. . . q . . . .
. . . . . . . .
. . N . . . . .
P P P P . P P P
R . B Q K B N R

As you can see, the first moves are called through the play() method which accepts the PGN format, but the latest one is made through playFen() by passing two FEN positions which represent one single chess move.

This is all for today, thanks so much for reading!

You may also be intersted in…

AI/ML

Trending AI/ML Article Identified & Digested via Granola by Ramsey Elbasheer; a Machine-Driven RSS Bot

%d bloggers like this: