pgn to json/php array parser
PHP
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
test
Board0x88Config.php
CHESS_JSON.php
DGTGameParser.php
FenParser0x88.php
GameParser.php
MoveBuilder.php
PgnGameParser.php
PgnParser.php
README.md
autoload.php
composer.json
composer.phar

README.md

PGN to PHP array parser

PHP class for conversion of Chess PGN files to PHP array or JSON.

This is the chess parser used in DHTML Chess at dhtml-chess.com

License: LGPL (Lesser General Public License).

Example of use:
1) Import games from PGN file:
<?php
$parser = new PgnParser('my-games.pgn');
echo json_encode($parser->getGames());
?>

This will give you data in this format:

[
    {
        "metadata":{
            "blackelo":"2400",
            "opening":"Grunfeld",
            "time":"10:41:37",
            "variation":"Three Knights Variation",
            "whiteelo":"2400",
            "whitetype":"human",
            "blacktype":"human",
            "castle":1
        },
        "event":"Computer chess game",
        "site":"BORROW-PC",
        "date":"2013.01.19",
        "round":"?",
        "white":"White player",
        "black":"Black player",
        "result":"*",
        "eco":"D90",
        "timecontrol":"300",
        "termination":"unterminated",
        "plycount":"21",
        "fen":"rnbqkbnr\/pppppppp\/8\/8\/8\/8\/PPPPPPPP\/RNBQKBNR w KQkq - 0 1",
        "moves":[
            {
                "m":"e4",
                "from":"e2",
                "to":"e4",
                "fen":"rnbqkbnr\/pppppppp\/8\/8\/4P3\/8\/PPPP1PPP\/RNBQKBNR b KQkq - 0 1"
            },
            {
                "m":"d5",
                "variations":[
                    [
                        {
                            "m":"e5",
                            "comment":"Test comment before",
                            "from":"e7",
                            "to":"e5",
                            "fen":"rnbqkbnr\/pppp1ppp\/8\/4p3\/4P3\/8\/PPPP1PPP\/RNBQKBNR w KQkq - 0 2"
                        },
                        {
                            "m":"Nf3",
                            "comment":"Test comment after",
                            "from":"g1",
                            "to":"f3",
                            "fen":"rnbqkbnr\/pppp1ppp\/8\/4p3\/4P3\/5N2\/PPPP1PPP\/RNBQKB1R b KQkq - 1 2"
                        },
                        {
                            "m":"Nc6",
                            "from":"b8",
                            "to":"c6",
                            "fen":"r1bqkbnr\/pppp1ppp\/2n5\/4p3\/4P3\/5N2\/PPPP1PPP\/RNBQKB1R w KQkq - 2 3"
                        },
                        {
                            "m":"Bc4",
                            "from":"f1",
                            "to":"c4",
                            "fen":"r1bqkbnr\/pppp1ppp\/2n5\/4p3\/2B1P3\/5N2\/PPPP1PPP\/RNBQK2R b KQkq - 3 3"
                        },
                        {
                            "m":"Nf6",
                            "variations":[
                                [
                                    {
                                        "m":"d6",
                                        "from":"d7",
                                        "to":"d6",
                                        "fen":"r1bqkbnr\/ppp2ppp\/2np4\/4p3\/2B1P3\/5N2\/PPPP1PPP\/RNBQK2R w KQkq - 0 4"
                                    },
                                    {
                                        "m":"O-O",
                                        "comment":"(O-O Ng8-f6 Nb1-c3 Nc6-d4 Nf3-g5 d6-d5 e4xd5 h7-h6 Ng5-e4 c7-c6 d5xc6 Nf6xe4 Nc3xe4 b7xc6) +0.48\/11 8",
                                        "from":"e1",
                                        "to":"g1",
                                        "fen":"r1bqkbnr\/ppp2ppp\/2np4\/4p3\/2B1P3\/5N2\/PPPP1PPP\/RNBQ1RK1 b kq - 1 4"
                                    },
                                    {
                                        "m":"Nf6",
                                        "from":"g8",
                                        "to":"f6",
                                        "fen":"r1bqkb1r\/ppp2ppp\/2np1n2\/4p3\/2B1P3\/5N2\/PPPP1PPP\/RNBQ1RK1 w kq - 2 5"
                                    },
                                    {
                                        "m":"Nc3",
                                        "comment":"Last move in variation",
                                        "from":"b1",
                                        "to":"c3",
                                        "fen":"r1bqkb1r\/ppp2ppp\/2np1n2\/4p3\/2B1P3\/2N2N2\/PPPP1PPP\/R1BQ1RK1 b kq - 3 5"
                                    }
                                ]
                            ],
                            "from":"g8",
                            "to":"f6",
                            "fen":"r1bqkb1r\/pppp1ppp\/2n2n2\/4p3\/2B1P3\/5N2\/PPPP1PPP\/RNBQK2R w KQkq - 4 4"
                        },
                        {
                            "m":"O-O",
                            "comment":"Variation ended",
                            "from":"e1",
                            "to":"g1",
                            "fen":"r1bqkb1r\/pppp1ppp\/2n2n2\/4p3\/2B1P3\/5N2\/PPPP1PPP\/RNBQ1RK1 b kq - 5 4"
                        },
                        {
                            "m":"d6",
                            "from":"d7",
                            "to":"d6",
                            "fen":"r1bqkb1r\/ppp2ppp\/2np1n2\/4p3\/2B1P3\/5N2\/PPPP1PPP\/RNBQ1RK1 w kq - 0 5"
                        }
                    ]
                ],
                "from":"d7",
                "to":"d5",
                "fen":"rnbqkbnr\/ppp1pppp\/8\/3p4\/4P3\/8\/PPPP1PPP\/RNBQKBNR w KQkq - 0 2"
            },
            {
                "m":"exd5",
                "comment":"Variation ended",
                "from":"e4",
                "to":"d5",
                "fen":"rnbqkbnr\/ppp1pppp\/8\/3P4\/8\/8\/PPPP1PPP\/RNBQKBNR b KQkq - 0 2"
            },
            {
                "m":"Nf6",
                "from":"g8",
                "to":"f6",
                "fen":"rnbqkb1r\/ppp1pppp\/5n2\/3P4\/8\/8\/PPPP1PPP\/RNBQKBNR w KQkq - 1 3"
            },
            {
                "m":"c4",
                "variations":[
                    [
                        {
                            "m":"Nf3?!",
                            "from":"g1",
                            "to":"f3",
                            "fen":"rnbqkb1r\/ppp1pppp\/5n2\/3P4\/8\/5N2\/PPPP1PPP\/RNBQKB1R b KQkq - 2 3"
                        },
                        {
                            "m":"Qxd5",
                            "from":"d8",
                            "to":"d5",
                            "fen":"rnb1kb1r\/ppp1pppp\/5n2\/3q4\/8\/5N2\/PPPP1PPP\/RNBQKB1R w KQkq - 0 4"
                        },
                        {
                            "m":"Nc3",
                            "from":"b1",
                            "to":"c3",
                            "fen":"rnb1kb1r\/ppp1pppp\/5n2\/3q4\/8\/2N2N2\/PPPP1PPP\/R1BQKB1R b KQkq - 1 4"
                        },
                        {
                            "m":"Qa5",
                            "from":"d5",
                            "to":"a5",
                            "fen":"rnb1kb1r\/ppp1pppp\/5n2\/q7\/8\/2N2N2\/PPPP1PPP\/R1BQKB1R w KQkq - 2 5"
                        },
                        {
                            "m":"d4",
                            "from":"d2",
                            "to":"d4",
                            "fen":"rnb1kb1r\/ppp1pppp\/5n2\/q7\/3P4\/2N2N2\/PPP2PPP\/R1BQKB1R b KQkq - 0 5"
                        }
                    ]
                ],
                "from":"c2",
                "to":"c4",
                "fen":"rnbqkb1r\/ppp1pppp\/5n2\/3P4\/2P5\/8\/PP1P1PPP\/RNBQKBNR b KQkq - 0 3"
            },
            {
                "m":"Bf5",
                "comment":"Variation ended",
                "variations":[
                    [
                        {
                            "m":"Nbd7",
                            "from":"b8",
                            "to":"d7",
                            "fen":"r1bqkb1r\/pppnpppp\/5n2\/3P4\/2P5\/8\/PP1P1PPP\/RNBQKBNR w KQkq - 1 4"
                        },
                        {
                            "m":"Nf3",
                            "from":"g1",
                            "to":"f3",
                            "fen":"r1bqkb1r\/pppnpppp\/5n2\/3P4\/2P5\/5N2\/PP1P1PPP\/RNBQKB1R b KQkq - 2 4"
                        },
                        {
                            "m":"Nb6",
                            "from":"d7",
                            "to":"b6",
                            "fen":"r1bqkb1r\/ppp1pppp\/1n3n2\/3P4\/2P5\/5N2\/PP1P1PPP\/RNBQKB1R w KQkq - 3 5"
                        },
                        {
                            "m":"d4",
                            "from":"d2",
                            "to":"d4",
                            "fen":"r1bqkb1r\/ppp1pppp\/1n3n2\/3P4\/2PP4\/5N2\/PP3PPP\/RNBQKB1R b KQkq d3 0 5"
                        },
                        {
                            "m":"g6",
                            "from":"g7",
                            "to":"g6",
                            "fen":"r1bqkb1r\/ppp1pp1p\/1n3np1\/3P4\/2PP4\/5N2\/PP3PPP\/RNBQKB1R w KQkq - 0 6"
                        },
                        {
                            "m":"Nc3",
                            "from":"b1",
                            "to":"c3",
                            "fen":"r1bqkb1r\/ppp1pp1p\/1n3np1\/3P4\/2PP4\/2N2N2\/PP3PPP\/R1BQKB1R b KQkq - 1 6"
                        },
                        {
                            "m":"Qd6",
                            "from":"d8",
                            "to":"d6",
                            "fen":"r1b1kb1r\/ppp1pp1p\/1n1q1np1\/3P4\/2PP4\/2N2N2\/PP3PPP\/R1BQKB1R w KQkq - 2 7"
                        }
                    ]
                ],
                "from":"c8",
                "to":"f5",
                "fen":"rn1qkb1r\/ppp1pppp\/5n2\/3P1b2\/2P5\/8\/PP1P1PPP\/RNBQKBNR w KQkq - 1 4"
            },
            {
                "m":"Nf3",
                "from":"g1",
                "to":"f3",
                "fen":"rn1qkb1r\/ppp1pppp\/5n2\/3P1b2\/2P5\/5N2\/PP1P1PPP\/RNBQKB1R b KQkq - 2 4"
            }
        ]
    }
]
2) Create parser from PGN String
$pgn = '[Event "Moscow Championship (blitz) 2015"]
[Site "Moscow RUS"]
[Date "2015.09.06"]
[Round "19"]
[White "Morozevich, Alexander"]
[Black "Dubov, Daniil"]
[Result "0-1"]
[ECO "B20"]
[WhiteElo "2711"]
[BlackElo "2661"]
[PlyCount "146"]
[EventDate "2015.09.06"]

1. e4 c5 2. g3 g6 3. Bg2 Bg7 4. d3 Nc6 5. f4 e6 6. Nf3 d5 7. O-O Nf6 8. e5 Nd7
9. c4 Nb6 10. Qe2 O-O 11. Nc3 f6 12. exf6 Bxf6 13. Kh1 Bd7 14. Bd2 Nd4 15. Nxd4
cxd4 16. Nd1 dxc4 17. dxc4 Bc6 18. Bxc6 bxc6 19. Nf2 c5 20. Rae1 Qd7 21. b3
Rfe8 22. Nd3 Rac8 23. Qe4 Qc6 24. g4 Qxe4+ 25. Rxe4 Nd7 26. Be1 h5 27. gxh5
gxh5 28. Rf3 Kh7 29. Bf2 Kg6 30. Rxe6 Kf5 31. Rd6 Nb6 32. Rh3 h4 33. Kg2 Be7
34. Rh6 Ke4 35. Re6+ Kf5 36. Re5+ Kg6 37. Kf3 Nd7 38. Re6+ Kf7 39. f5 Bf6 40.
Bxh4 Rxe6 41. fxe6+ Kxe6 42. Bg3 Rf8 43. Rh5 Bg5+ 44. Kg2 Be3 45. Rd5 Re8 46.
Rd6+ Ke7 47. Ra6 Ra8 48. h4 Nf6 49. Nxc5 Nd7 50. Nd3 Rg8 51. Kf3 Rf8+ 52. Ke2
Rg8 53. Bf4 Bxf4 54. Nxf4 Nc5 55. Rxa7+ Kd6 56. b4 Re8+ 57. Kf3 Re3+ 58. Kg4
Ne4 59. Ra6+ Kd7 60. Ra5 Nf2+ 61. Kf5 d3 62. Rd5+ Kc7 63. h5 Rf3 64. Ke5 Re3+
65. Kf5 Rf3 66. h6 Nh3 67. h7 Rxf4+ 68. Kg6 Rh4 69. Kg7 Nf4 70. Rc5+ Kd6 71.
Rc8 Ne6+ 72. Kf6 d2 73. c5+ Kd7 0-1';

$parser = new PgnParser();
$parser->setPgnContent($pgn);
$game = $parser->getFirstGame();
echo json_encode($game);
3) Create a game programatically.

This uses the FenParser0x88 class:

$parser = new FenParser0x88();
$parser->newGame();
$parser->move("g1f3");
$notation =  $parser->getNotation(); // returns Nf3
$fen = $parser->getFen();
// $fen = rnbqkbnr/pppppppp/8/8/8/5N2/PPPPPPPP/RNBQKB1R b KQkq - 1 1
4) Get valid moves
$parser = new FenParser0x88('6k1/6p1/4n3/8/8/8/B7/6K1 b - - 0 1');
$validBlackMoves = $parser->getValidMovesBoardCoordinates("black");
echo json_encode($validBlackMoves);

which outputs

{"g8":["f7","h7","f8","h8"],"g7":["g6","g5"],"e6":[]}

where key, example "g8" is the square of a piece and ["f7","h7","f8","h8"] are all the valid moves for the piece on that square.

In this example, there's a knight on e6. However, it cannot move because it is pinned by a white bishop on a2. Thus, the valid moves array for "e6" is empty.