From d0fa9f107efa46b04009c60703df01c1c773d61e Mon Sep 17 00:00:00 2001 From: programarivm Date: Wed, 2 Oct 2024 23:46:49 +0200 Subject: [PATCH 1/2] Implemented StockfishAsyncTask --- src/Command/Game/Cli.php | 2 +- src/Command/Game/StockfishAsyncTask.php | 31 +++++++++++++++++++++++++ src/Command/Game/StockfishCommand.php | 11 ++++++--- 3 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 src/Command/Game/StockfishAsyncTask.php diff --git a/src/Command/Game/Cli.php b/src/Command/Game/Cli.php index b2e0df6..b62a67d 100644 --- a/src/Command/Game/Cli.php +++ b/src/Command/Game/Cli.php @@ -34,7 +34,7 @@ public function __construct(Pool $pool, Db $db) $this->commands->attach(new ResignCommand($db)); $this->commands->attach(new RestartCommand($db)); $this->commands->attach(new StartCommand($db)); - $this->commands->attach(new StockfishCommand()); + $this->commands->attach((new StockfishCommand())->setPool($pool)); $this->commands->attach(new TutorFenCommand()); } diff --git a/src/Command/Game/StockfishAsyncTask.php b/src/Command/Game/StockfishAsyncTask.php new file mode 100644 index 0000000..6973d6d --- /dev/null +++ b/src/Command/Game/StockfishAsyncTask.php @@ -0,0 +1,31 @@ +params = $params; + $this->gameMode = $gameMode; + $this->command = $command; + + } + + public function configure() + { + } + + public function run() + { + return $this->gameMode->res($this->params, $this->command); + } +} diff --git a/src/Command/Game/StockfishCommand.php b/src/Command/Game/StockfishCommand.php index 7fc0f2e..75eb723 100644 --- a/src/Command/Game/StockfishCommand.php +++ b/src/Command/Game/StockfishCommand.php @@ -26,8 +26,13 @@ public function run(AbstractSocket $socket, array $argv, int $id) $params = json_decode(stripslashes($argv[1]), true); $gameMode = $socket->getGameModeStorage()->getById($id); - return $socket->getClientStorage()->send([$id], - $gameMode->res($params, $this) - ); + $this->pool->add(new StockfishAsyncTask($params, $gameMode, $this)) + ->then(function ($result) use ($socket, $id) { + return $socket->getClientStorage()->send([$id], [ + $this->name => $result, + ]); + }); + + // $this->pool->wait(); } } From 9f8da511ba3568233109e9bb78f3bdb6db8f4364 Mon Sep 17 00:00:00 2001 From: programarivm Date: Thu, 3 Oct 2024 12:05:10 +0200 Subject: [PATCH 2/2] Implemented StockfishAsyncTask --- src/Command/Game/Game.php | 36 ++---------------------- src/Command/Game/Mode/AbstractMode.php | 17 +----------- src/Command/Game/StartCommand.php | 2 +- src/Command/Game/StockfishAsyncTask.php | 37 +++++++++++++++++++------ src/Command/Game/StockfishCommand.php | 24 ++++++++++------ src/Socket/Ratchet/GameWebSocket.php | 7 ----- src/Socket/Workerman/GameWebSocket.php | 7 ----- 7 files changed, 48 insertions(+), 82 deletions(-) diff --git a/src/Command/Game/Game.php b/src/Command/Game/Game.php index 565ec52..6ab55af 100644 --- a/src/Command/Game/Game.php +++ b/src/Command/Game/Game.php @@ -2,9 +2,6 @@ namespace ChessServer\Command\Game; -use Chess\Computer\GrandmasterMove; -use Chess\UciEngine\UciEngine; -use Chess\UciEngine\Details\Limit; use Chess\Variant\AbstractBoard; use Chess\Variant\Chess960\Board as Chess960Board; use Chess\Variant\Chess960\StartPosition as Chess960StartPosition; @@ -33,20 +30,14 @@ class Game private string $mode; - private null|GrandmasterMove $gmMove; - private string $resignation = ''; private string $abandoned = ''; - public function __construct( - string $variant, - string $mode, - null|GrandmasterMove $gmMove = null - ) { + public function __construct(string $variant, string $mode) + { $this->variant = $variant; $this->mode = $mode; - $this->gmMove = $gmMove; if ($this->variant === self::VARIANT_960) { $startPos = (new Chess960StartPosition())->create(); @@ -123,29 +114,6 @@ public function state(): object ]; } - public function computer(array $options = [], array $params = []): ?array - { - if ($this->gmMove) { - if ($move = $this->gmMove->move($this->board)) { - return $move; - } - } - - $limit = new Limit(); - $limit->depth = $params['depth']; - $stockfish = (new UciEngine('/usr/games/stockfish'))->setOption('Skill Level', $options['Skill Level']); - $analysis = $stockfish->analysis($this->board, $limit); - - $clone = $this->board->clone(); - $clone->playLan($this->board->turn, $analysis['bestmove']); - $history = $clone->history; - $end = end($history); - - return [ - 'pgn' => $end['move']['pgn'], - ]; - } - public function play(string $color, string $pgn): bool { return $this->board->play($color, $pgn); diff --git a/src/Command/Game/Mode/AbstractMode.php b/src/Command/Game/Mode/AbstractMode.php index f8ab4bf..fa8fe8d 100644 --- a/src/Command/Game/Mode/AbstractMode.php +++ b/src/Command/Game/Mode/AbstractMode.php @@ -5,7 +5,6 @@ use ChessServer\Command\Game\Game; use ChessServer\Command\Game\LegalCommand; use ChessServer\Command\Game\PlayLanCommand; -use ChessServer\Command\Game\StockfishCommand; use ChessServer\Command\Game\UndoCommand; use Firebase\JWT\JWT; use Firebase\JWT\Key; @@ -91,21 +90,7 @@ public function res($params, $cmd) 'isValid' => $isValid, ], ]; - - case StockfishCommand::class: - if (!isset($this->game->state()->end)) { - $computer = $this->game->computer($params['options'], $params['params']); - if ($computer['pgn']) { - $this->game->play($this->game->state()->turn, $computer['pgn']); - } - } - return [ - $cmd->name => [ - ...(array) $this->game->state(), - 'variant' => $this->game->getVariant(), - ], - ]; - + case UndoCommand::class: $board = $this->game->getBoard()->undo(); $this->game->setBoard($board); diff --git a/src/Command/Game/StartCommand.php b/src/Command/Game/StartCommand.php index 895e59e..0578740 100644 --- a/src/Command/Game/StartCommand.php +++ b/src/Command/Game/StartCommand.php @@ -199,7 +199,7 @@ public function run(AbstractSocket $socket, array $argv, int $id) $board = FenToBoardFactory::create($params['settings']['fen'], new ClassicalBoard()); $game = (new Game($params['variant'], $params['mode']))->setBoard($board); } else { - $game = new Game($params['variant'], $params['mode'], $socket->getGmMove()); + $game = new Game($params['variant'], $params['mode']); } $payload = [ 'iss' => $_ENV['JWT_ISS'], diff --git a/src/Command/Game/StockfishAsyncTask.php b/src/Command/Game/StockfishAsyncTask.php index 6973d6d..f013be9 100644 --- a/src/Command/Game/StockfishAsyncTask.php +++ b/src/Command/Game/StockfishAsyncTask.php @@ -2,30 +2,51 @@ namespace ChessServer\Command\Game; +use Chess\Computer\GrandmasterMove; +use Chess\UciEngine\UciEngine; +use Chess\UciEngine\Details\Limit; +use Chess\Variant\Classical\Board; +use ChessServer\Socket\AbstractSocket; use Spatie\Async\Task; class StockfishAsyncTask extends Task { - private $params; + private array $params; - private $gameMode; + private Board $board; - private $command; + private GrandmasterMove $gmMove; - public function __construct($params, $gameMode, $command) + public function __construct($params, $board) { $this->params = $params; - $this->gameMode = $gameMode; - $this->command = $command; - + $this->board = $board; } public function configure() { + $this->gmMove = new GrandmasterMove(AbstractSocket::DATA_FOLDER.'/players.json'); } public function run() { - return $this->gameMode->res($this->params, $this->command); + if ($move = $this->gmMove->move($this->board)) { + return $move; + } + + $limit = new Limit(); + $limit->depth = $this->params['params']['depth']; + $stockfish = (new UciEngine('/usr/games/stockfish')) + ->setOption('Skill Level', $this->params['options']['Skill Level']); + $analysis = $stockfish->analysis($this->board, $limit); + + $clone = $this->board->clone(); + $clone->playLan($this->board->turn, $analysis['bestmove']); + $history = $clone->history; + $end = end($history); + + return [ + 'pgn' => $end['move']['pgn'], + ]; } } diff --git a/src/Command/Game/StockfishCommand.php b/src/Command/Game/StockfishCommand.php index 75eb723..c71f2f3 100644 --- a/src/Command/Game/StockfishCommand.php +++ b/src/Command/Game/StockfishCommand.php @@ -24,15 +24,21 @@ public function validate(array $argv) public function run(AbstractSocket $socket, array $argv, int $id) { $params = json_decode(stripslashes($argv[1]), true); - $gameMode = $socket->getGameModeStorage()->getById($id); + $game = $socket->getGameModeStorage()->getById($id)->getGame(); - $this->pool->add(new StockfishAsyncTask($params, $gameMode, $this)) - ->then(function ($result) use ($socket, $id) { - return $socket->getClientStorage()->send([$id], [ - $this->name => $result, - ]); - }); - - // $this->pool->wait(); + if (!isset($game->state()->end)) { + $this->pool->add(new StockfishAsyncTask($params, $game->getBoard())) + ->then(function ($result) use ($socket, $id, $game) { + if ($result['pgn']) { + $game->play($game->state()->turn, $result['pgn']); + } + return $socket->getClientStorage()->send([$id], [ + $this->name => [ + ...(array) $game->state(), + 'variant' => $game->getVariant(), + ], + ]); + }); + } } } diff --git a/src/Socket/Ratchet/GameWebSocket.php b/src/Socket/Ratchet/GameWebSocket.php index 8cd4efd..73c9802 100644 --- a/src/Socket/Ratchet/GameWebSocket.php +++ b/src/Socket/Ratchet/GameWebSocket.php @@ -2,7 +2,6 @@ namespace ChessServer\Socket\Ratchet; -use Chess\Computer\GrandmasterMove; use ChessServer\Command\Parser; use ChessServer\Command\Game\GameModeStorage; use ChessServer\Socket\DbReconnectTrait; @@ -20,15 +19,9 @@ public function __construct(Parser $parser) $this->reconnect(); }); - $this->gmMove = new GrandmasterMove(self::DATA_FOLDER.'/players.json'); $this->gameModeStorage = new GameModeStorage(); } - public function getGmMove(): GrandmasterMove - { - return $this->gmMove; - } - public function getGameModeStorage(): GameModeStorage { return $this->gameModeStorage; diff --git a/src/Socket/Workerman/GameWebSocket.php b/src/Socket/Workerman/GameWebSocket.php index ade54be..ae7e440 100644 --- a/src/Socket/Workerman/GameWebSocket.php +++ b/src/Socket/Workerman/GameWebSocket.php @@ -2,7 +2,6 @@ namespace ChessServer\Socket\Workerman; -use Chess\Computer\GrandmasterMove; use ChessServer\Command\Parser; use ChessServer\Command\Game\GameModeStorage; use ChessServer\Socket\DbReconnectTrait; @@ -26,17 +25,11 @@ public function __construct(string $socketName, array $context, Parser $parser) }); }; - $this->gmMove = new GrandmasterMove(self::DATA_FOLDER.'/players.json'); $this->gameModeStorage = new GameModeStorage(); $this->connect()->message()->error()->close(); } - public function getGmMove(): GrandmasterMove - { - return $this->gmMove; - } - public function getGameModeStorage(): GameModeStorage { return $this->gameModeStorage;