Giter Site home page Giter Site logo

chesslablab / chess-server Goto Github PK

View Code? Open in Web Editor NEW
36.0 3.0 22.0 18.51 MB

Asynchronous PHP chess server.

Home Page: https://chess-server.docs.chesslablab.org/

License: MIT License

PHP 99.64% Shell 0.36%
chess server websocket telnet php pgn async fen lan san

chess-server's Introduction

PHP Chess Server

License: MIT Contributors

Asynchronous PHP chess server.

Documentation

Read the latest docs here.

License

The PHP Chess Server is open-sourced software licensed under the MIT license.

Contributions

We encourage you to contribute to PHP Chess Server! Please follow the Contributing Guidelines.

Made with contrib.rocks.

chess-server's People

Contributors

apoorvpal01 avatar braunson avatar codemaster7000 avatar ctzxvulkan avatar dependabot[bot] avatar jeffersonsimaogoncalves avatar kirillarutyunov avatar mihaescuvlad avatar pen-y-fan avatar programarivm avatar smashedfrenzy16 avatar tolik518 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

chess-server's Issues

Snake case the command names containing several words

Command names containing several words should be snake cased for better readability, as it is described below.

  • /heuristicpicture <--> /heuristic_picture
  • /ischeck <--> /is_check
  • /ismate <--> /is_mate
  • /playfen <--> /play_fen
  • /undomove <--> /undo_move

Happy coding and keep it up.

Add a command to fetch the events happening in the game

This issue is intended to practice software architecture skills as well as unit testing.

As you may have noted, there's a one-to-one correspondence between the Chess\Game methods described in the PHP Chess docs and the commands available in the chess server:

  • ascii(): string <-> ChessServer\Command\AsciiCommand.php
  • captures(): array <-> ChessServer\Command\CapturesCommand.php
  • castling(): ?array <-> ChessServer\Command\CastlingCommand.php
  • ...

However, the ChessServer\Command\EventsCommand.php is missing.

The missing file should be added. Also, the corresponding unit test should be written in the tests/unit/Command folder as per the existing conventions.

Happy learning and coding!

Add a new game mode called GrandmasterMode

At the present moment, the chess server can differentiate among these game modes:

  • src/GameMode/AnalysisMode.php
  • src/GameMode/LoadFenMode.php
  • src/GameMode/LoadPgnMode.php
  • src/GameMode/PlayFriendMode.php

However, a new game mode needs to be added to allow playing chess like a grandmaster:

  • src/GameMode/GrandmasterMode.php

Keep it up, and happy learning!

See:

Allow to propose a takeback

A new method to allow proposing a takeback should be implemented in the Chess\Game class as described in chesslablab/php-chess#55.

As you may have noted, there's a one-to-one correspondence between the Chess\Game methods described in the PHP Chess docs and the commands available in the chess server:

ascii(): string <-> ChessServer\Command\AsciiCommand.php
captures(): array <-> ChessServer\Command\CapturesCommand.php
castling(): ?array <-> ChessServer\Command\CastlingCommand.php
...

However, the ChessServer\Command\TakebackCommand.php is missing.

The missing file should be added once the takeback method has been implemented in Chess\Game.

Also see chesslablab/spablab#132.

Unit test the /castling command

This issue is intended to practice software architecture skills as well as unit testing.

As you may have noted, there's a one-to-one correspondence between the Chess\Game methods described in the PHP Chess Docs and the commands available in the chess server:

  • ascii(): string <-> ChessServer\Command\AsciiCommand.php
  • captures(): array <-> ChessServer\Command\CapturesCommand.php
  • castling(): ?array <-> ChessServer\Command\CastlingCommand.php
  • ...

All commands should be unit tested in ChessServer\Tests\Unit\Command. However, the ChessServer\Tests\Unit\Command\CastlingTest.php file is missing.

The missing file should be added as per the existing conventions.

Happy learning and coding!

Fix the notices that are thrown when loading an invalid FEN

The chess server will complain with the following PHP notices after trying to load foo as a FEN string:

figure-01

$ php cli/ws-server.php 
Welcome to PHP Chess Server
Commands available:
/accept {"id":"id"} Accepts a friend request to play a game.
/ascii Prints the ASCII representation of the game.
/castling Gets the castling status.
/captures Gets the pieces captured by both players.
/fen Prints the FEN string representation of the game.
/heuristicpicture Takes a balanced heuristic picture of the current 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":"string"} Gets a piece by its position on the board.
/pieces {"color":["w","b"]} Gets the pieces on the board by color.
/playfen {"fen":"string"} Plays a chess move in shortened FEN format.
/quit Quits a game.
/start {"mode":["analysis","loadfen","playfriend"],"fen":"string","color":["w","b"],"min":"int"} Starts a new game.
/status The current game status.

Listening to commands...
PHP Notice:  Undefined offset: 2 in /home/standard/projects/chess-server/vendor/chesslablab/php-chess/src/FEN/StringToBoard.php on line 89
PHP Notice:  Undefined offset: 2 in /home/standard/projects/chess-server/vendor/chesslablab/php-chess/src/FEN/StringToBoard.php on line 95
PHP Notice:  Undefined offset: 2 in /home/standard/projects/chess-server/vendor/chesslablab/php-chess/src/FEN/StringToBoard.php on line 95
PHP Notice:  Undefined offset: 1 in /home/standard/projects/chess-server/vendor/chesslablab/php-chess/src/FEN/StringToBoard.php on line 52
PHP Notice:  Undefined offset: 2 in /home/standard/projects/chess-server/vendor/chesslablab/php-chess/src/FEN/StringToBoard.php on line 52
PHP Notice:  Undefined offset: 3 in /home/standard/projects/chess-server/vendor/chesslablab/php-chess/src/FEN/StringToBoard.php on line 52

Log the number of current connections

The number of current connections should be written in the log every time a new connection is open.

At the present moment this is how the log looks like:

$ cat storage/pchess.log
...
[2021-09-18T17:01:14.803013+00:00] pchess.net.INFO: New connection {"id":654} []
[2021-09-18T17:01:14.938909+00:00] pchess.net.INFO: Sent message {"id":654,"res":{"/start":{"mode":"analysis"}}} []
[2021-09-18T17:01:17.293531+00:00] pchess.net.INFO: Sent message {"id":654,"res":{"/piece":{"stdClass":{"color":"w","identity":"P","position":"e2","moves":["e3","e4"]}}}} []
[2021-09-18T17:01:18.115265+00:00] pchess.net.INFO: Sent message {"id":654,"res":{"/playfen":{"turn":"w","legal":true,"check":false,"mate":false,"movetext":"1.e4","fen":"rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3"}}} []

However, it should look like this:

$ cat storage/pchess.log
...
[2021-09-18T17:01:14.803013+00:00] pchess.net.INFO: New connection {"id":654, "n":8} []
[2021-09-18T17:01:14.938909+00:00] pchess.net.INFO: Sent message {"id":654,"res":{"/start":{"mode":"analysis"}}} []
[2021-09-18T17:01:17.293531+00:00] pchess.net.INFO: Sent message {"id":654,"res":{"/piece":{"stdClass":{"color":"w","identity":"P","position":"e2","moves":["e3","e4"]}}}} []
[2021-09-18T17:01:18.115265+00:00] pchess.net.INFO: Sent message {"id":654,"res":{"/playfen":{"turn":"w","legal":true,"check":false,"mate":false,"movetext":"1.e4","fen":"rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3"}}} []

Thus, it's just the following line that needs an update:

[2021-09-18T17:01:14.803013+00:00] pchess.net.INFO: New connection {"id":654} []

Happy learning and coding!

Add a new command to allow restarting a game

Once the /rematch command has been successfully added, a new command should be implemented now in order to allow restarting a game if accepting a rematch. The /restart command is to be used by passing the hash of the game as an argument as described in the example below.

/restart 51e2e0b55f862b69e0f6fad3951b44c1

See:

Happy learning and coding!

Update files in the ChessServer\Command namespace

The $dependsOn property should be updated in all files in the ChessServer\Command namespace depending on the StartCommand.

  • src/Command/AcceptFriendRequestCommand.php
  • src/Command/AsciiCommand.php
  • ...
  • src/Command/StatusCommand.php

Specifically, Start::class should be replaced with StartCommand::class as it is shown in the following example.

<?php

namespace ChessServer\Command;

class AsciiCommand extends AbstractCommand
{
    public function __construct()
    {
        $this->name = '/ascii';
        $this->description = 'Prints the ASCII representation of the game.';
        $this->dependsOn = [
            StartCommand::class,
        ];
    }

    public function validate(array $argv)
    {
        return count($argv) - 1 === 0;
    }
}

Happy learning and coding!

Keep it up.

Refactor the server's response to a /playfen request

At this moment /playfen is responding with a basic {"legal": true} or {"legal": false} string, but it makes sense to add some more lightweight data for the client app to display.

Possibly the simplest thing to do at this stage is to just refactor the response as described in the following example:

{
  "legal": true,
  "movetext": "1.e4 e5"
}

See chesslablab/spablab#13

Secure the WebSocket connections

Now that a sandbox chess server has been setup for testing purposes, it seems as if the WebSocket connections should be secured in order for this demo to run without security issues.

Chrome:

Mixed Content: The page at 'https://programarivm.com/demo-redux-chess/' was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint 'ws://3.121.169.246:8080/'. This request has been blocked; this endpoint must be available over WSS.

Firefox:

Uncaught (in promise) DOMException: The operation is insecure.

Send the response of the /undomove command to both players

At the present moment, when a player sends the /undomove command to the server their opponent won't receive any confirmation from it and won't be able to undo the move accordingly. This is because by default the Socket.php sends a message to one player only as it is described in the code below.

<?php

namespace ChessServer;

..

class Socket implements MessageComponentInterface
{
    ...

    public function onMessage(ConnectionInterface $from, $msg)
    {
        ...

        if (is_a($cmd, AcceptFriendRequestCommand::class)) {
            if ($gameMode = $this->findGameMode($this->parser->argv[1])) {
                if ($this->syncGameModeWith($gameMode, $from)) {
                    $jwt = $gameMode->getJwt();
                    $decoded = JWT::decode($jwt, $_ENV['JWT_SECRET'], array('HS256'));
                    return $this->sendToMany($gameMode->getResourceIds(), [
                        $cmd->name => [
                            'jwt' => $jwt,
                            'hash' => md5($jwt),
                        ],
                    ]);
                }
            }
            return $this->sendToOne($from->resourceId, [
                $cmd->name => [
                    'mode' => PlayFriendMode::NAME,
                    'message' =>  'This friend request could not be accepted.',
                ],
            ]);
        } elseif (is_a($cmd, DrawCommand::class)) {
            if (is_a($gameMode, PlayFriendMode::class)) {
                return $this->sendToMany(
                    $gameMode->getResourceIds(),
                    $gameMode->res($this->parser->argv, $cmd)
                );
            }
        } elseif (is_a($cmd, PlayFenCommand::class)) {

            ...

        } elseif (is_a($cmd, QuitCommand::class)) {

            ...
            
        } elseif (is_a($cmd, ResignCommand::class)) {

            ...
            
        } elseif (is_a($cmd, StartCommand::class)) {

            ...
            
        } elseif (is_a($cmd, TakebackCommand::class)) {
            ...
        } elseif ($gameMode) {
            return $this->sendToOne(
                $from->resourceId,
                $this->gameModes[$from->resourceId]->res($this->parser->argv, $cmd)
            );
        }
    }
    
    ...
}

Thus, the UndoMoveCommand should be added to the main if statement in a similar way as with DrawCommand in that the response needs to be sent to both players.


Described below is the sequence of commands that would allow Bob to propose a takeback to Alice after playing 1.e4 e5.

Alice:

$ websocat ws://localhost:8080
/start playfriend w 10
{"\/start":{"mode":"playfriend","jwt":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwY2hlc3MubmV0IiwiaWF0IjoxNjMyOTI4OTY4LCJjb2xvciI6InciLCJtaW4iOiIxMCIsImV4cCI6MTYzMjkyOTU2OH0.KAlahRGFjyg2NF7o7xlh4nV4HrcFng9JhM65IeiPPOQ","hash":"b9bef730966d51284303d9054d33fabb"}}
{"\/accept":{"jwt":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwY2hlc3MubmV0IiwiaWF0IjoxNjMyOTI4OTY4LCJjb2xvciI6InciLCJtaW4iOiIxMCIsImV4cCI6MTYzMjkyOTU2OH0.KAlahRGFjyg2NF7o7xlh4nV4HrcFng9JhM65IeiPPOQ","hash":"b9bef730966d51284303d9054d33fabb"}}
/playfen "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b"
{"\/playfen":{"turn":"w","legal":true,"check":false,"mate":false,"movetext":"1.e4","fen":"rnbqkbnr\/pppppppp\/8\/8\/4P3\/8\/PPPP1PPP\/RNBQKBNR b KQkq e3"}}
{"\/playfen":{"turn":"b","legal":true,"check":false,"mate":false,"movetext":"1.e4 e5","fen":"rnbqkbnr\/pppp1ppp\/8\/4p3\/4P3\/8\/PPPP1PPP\/RNBQKBNR w KQkq e6"}}
{"\/takeback":"propose"}
/takeback accept
{"\/takeback":"accept"}

Bob:

$ websocat ws://localhost:8080
/accept b9bef730966d51284303d9054d33fabb
{"\/accept":{"jwt":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwY2hlc3MubmV0IiwiaWF0IjoxNjMyOTI4OTY4LCJjb2xvciI6InciLCJtaW4iOiIxMCIsImV4cCI6MTYzMjkyOTU2OH0.KAlahRGFjyg2NF7o7xlh4nV4HrcFng9JhM65IeiPPOQ","hash":"b9bef730966d51284303d9054d33fabb"}}
{"\/playfen":{"turn":"w","legal":true,"check":false,"mate":false,"movetext":"1.e4","fen":"rnbqkbnr\/pppppppp\/8\/8\/4P3\/8\/PPPP1PPP\/RNBQKBNR b KQkq e3"}}
/playfen "rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR w"
{"\/playfen":{"turn":"b","legal":true,"check":false,"mate":false,"movetext":"1.e4 e5","fen":"rnbqkbnr\/pppp1ppp\/8\/4p3\/4P3\/8\/PPPP1PPP\/RNBQKBNR w KQkq e6"}}
/takeback propose
{"\/takeback":"propose"}
{"\/takeback":"accept"}
/undomove
{"\/undomove":true}

See chesslablab/spablab#153

Allow time increment in playfriend mode

A new parameter needs to be added to allow starting games with a time increment of n seconds, as described in the example below.

$ websocat ws://localhost:8080
/start playfriend w 10 3        
{"\/start":{"mode":"playfriend","jwt":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwY2hlc3MubmV0IiwiaWF0IjoxNjM4ODc4OTAxLCJjb2xvciI6InciLCJtaW4iOiIxMCIsImluY3JlbWVudCI6IjMiLCJleHAiOjE2Mzg4Nzk1MDF9._miJaIi0Qm-mvHka-vZ6aBVfJVsD2uDZDhnoMAaNfLU","hash":"713333c9ce51fe98a256732cf706215d"}}

In this example, a 10 minutes game is started with a time increment of 3 seconds.

See chesslablab/spablab#190

Unit test the /fen command

This issue is intended to practice software architecture skills as well as unit testing.

As you may have noted, there's a one-to-one correspondence between the Chess\Game methods described in the PHP Chess Docs and the commands available in the chess server:

  • ascii(): string <-> ChessServer\Command\AsciiCommand.php
  • captures(): array <-> ChessServer\Command\CapturesCommand.php
  • castling(): ?array <-> ChessServer\Command\CastlingCommand.php
  • ...

All commands should be unit tested in ChessServer\Tests\Unit\Command. However, the ChessServer\Tests\Unit\Command\FenTest.php file is missing.

The missing file should be added as per the existing conventions.

Happy learning and coding!

Unit test the /ascii command

This issue is intended to practice software architecture skills as well as unit testing.

As you may have noted, there's a one-to-one correspondence between the Chess\Game methods described in the PHP Chess Docs and the commands available in the chess server:

  • ascii(): string <-> ChessServer\Command\AsciiCommand.php
  • captures(): array <-> ChessServer\Command\CapturesCommand.php
  • castling(): ?array <-> ChessServer\Command\CastlingCommand.php
  • ...

All commands should be unit tested in the ChessServer\Tests\Unit\Command namespace; however, the ChessServer\Tests\Unit\Command\AsciiTest.php file is missing at the present moment.

The missing file should be added as per the existing conventions.

Happy learning and coding!

Order alphabetically the commands

The commands used in the main if block in ChessServer\Socket should be ordered alphabetically for better readability.

        ...
        if (is_a($cmd, AcceptFriendRequestCommand::class)) {
          ...
        } elseif (is_a($cmd, QuitCommand::class)) {
          ...
        } elseif (is_a($cmd, StartCommand::class)) {
          ...
        } elseif (is_a($cmd, PlayFenCommand::class)) {
          ...
        } elseif (is_a($cmd, TakebackCommand::class)) {
          ...
        } elseif (is_a($cmd, DrawCommand::class)) {
           ...
        } elseif (is_a($cmd, ResignCommand::class)) {
           ...
        } elseif ($gameMode) {
            return $this->sendToOne(
                $from->resourceId,
                $this->gameModes[$from->resourceId]->res($this->parser->argv, $cmd)
            );
        }
        ...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.