public function detectCheater(Game $game)
 {
     if ($game->getTurns() != $this->turns && $game->getTurns() != $this->turns + 1) {
         return false;
     }
     if ($game->getInvited()->getIsAi()) {
         return false;
     }
     // Detect client using internal AI
     $similarGames = $this->gameRepository->findSimilar($game, new DateTime('-5 minutes'));
     foreach ($similarGames as $similarGame) {
         if ($similarGame->getInvited()->getIsAi()) {
             return $game->getPlayer($similarGame->getInvited()->getColor());
         }
     }
     return false;
 }
Exemple #2
0
 /**
  * @depends testGameCreationStandard
  */
 public function testGamePlayerTurn(Document\Game $game)
 {
     $player = $game->getPlayer('white');
     $this->assertTrue($player->getIsMyTurn());
     $this->assertFalse($player->getOpponent()->getIsMyTurn());
     $game->setTurns($game->getTurns() + 1);
     $this->assertFalse($player->getIsMyTurn());
     $this->assertTrue($player->getOpponent()->getIsMyTurn());
 }
Exemple #3
0
 public function expandGame(Game $game)
 {
     return sprintf('game(%s,%s,%s,%s,%d,%s)', $game->getVariantName(), $game->getClockName(), $game->getIsRated() ? 'rated' : 'casual', $game->getIsPlayable() ? 'playable' : $game->getStatusMessage(), $game->getTurns(), $this->generator->generate('lichess_game', array('id' => $game->getId()), true));
 }
 public function findSimilar(Game $game, \DateTime $since)
 {
     return $this->createQueryBuilder()->field('id')->notEqual($game->getId())->field('updatedAt')->gt(new \MongoDate($since->getTimestamp()))->field('status')->equals(Game::STARTED)->field('turns')->equals($game->getTurns())->field('pgnMoves')->equals($game->getPgnMoves())->hint(array('updatedAt' => -1))->getQuery()->execute();
 }
Exemple #5
0
 public function isMyTurn()
 {
     return $this->game->getTurns() % 2 xor 'white' === $this->c;
 }
Exemple #6
0
 public function getIsMyTurn()
 {
     return $this->game->getTurns() % 2 xor 'white' === $this->color;
 }
Exemple #7
0
 /**
  * Transform a game to standard Forsyth Edwards Notation
  * http://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation
  */
 public static function export(Game $game, $positionOnly = false)
 {
     static $reverseClasses = array('Pawn' => 'p', 'Rook' => 'r', 'Knight' => 'n', 'Bishop' => 'b', 'Queen' => 'q', 'King' => 'k');
     $board = $game->getBoard();
     $emptySquare = 0;
     $forsyth = '';
     for ($y = 8; $y > 0; $y--) {
         for ($x = 1; $x < 9; $x++) {
             if ($piece = $board->getPieceByPosNoCheck($x, $y)) {
                 if ($emptySquare) {
                     $forsyth .= $emptySquare;
                     $emptySquare = 0;
                 }
                 $notation = $reverseClasses[$piece->getClass()];
                 if ('white' === $piece->getColor()) {
                     $notation = strtoupper($notation);
                 }
                 $forsyth .= $notation;
             } else {
                 ++$emptySquare;
             }
         }
         if ($emptySquare) {
             $forsyth .= $emptySquare;
             $emptySquare = 0;
         }
         $forsyth .= '/';
     }
     $forsyth = trim($forsyth, '/');
     if ($positionOnly) {
         return $forsyth;
     }
     // b ou w to indicate turn
     $forsyth .= ' ';
     $forsyth .= substr($game->getTurnColor(), 0, 1);
     // possibles castles
     $forsyth .= ' ';
     $hasCastle = false;
     $analyser = new Analyser($board);
     foreach ($game->getPlayers() as $player) {
         if ($analyser->canCastleKingSide($player)) {
             $hasCastle = true;
             $forsyth .= $player->isWhite() ? 'K' : 'k';
         }
         if ($analyser->canCastleQueenSide($player)) {
             $hasCastle = true;
             $forsyth .= $player->isWhite() ? 'Q' : 'q';
         }
     }
     if (!$hasCastle) {
         $forsyth .= '-';
     }
     // en passant
     $enPassant = '-';
     foreach (PieceFilter::filterClass(PieceFilter::filterAlive($game->getPieces()), 'Pawn') as $piece) {
         if ($piece->getFirstMove() === $game->getTurns() - 1) {
             $color = $piece->getPlayer()->getColor();
             $y = $piece->getY();
             if ($color === 'white' && 4 === $y || $color === 'black' && 5 === $y) {
                 $enPassant = Board::posToKey($piece->getX(), 'white' === $color ? $y - 1 : $y + 1);
                 break;
             }
         }
     }
     $forsyth .= ' ' . $enPassant;
     // Halfmove clock: This is the number of halfmoves since the last pawn advance or capture.
     // This is used to determine if a draw can be claimed under the fifty-move rule.
     $forsyth .= ' ' . $game->getHalfmoveClock();
     // Fullmove number: The number of the full move. It starts at 1, and is incremented after Black's move.
     $forsyth .= ' ' . $game->getFullMoveNumber();
     return $forsyth;
 }
Exemple #8
0
 protected function updateElo(Game $game)
 {
     // Game can be aborted
     if (!$game->getIsFinished()) {
         return;
     }
     if (!$game->getIsRated()) {
         return;
     }
     // Don't rate games with less than 2 moves
     if ($game->getTurns() < 2) {
         return;
     }
     $white = $game->getPlayer('white');
     $black = $game->getPlayer('black');
     $whiteUser = $white->getUser();
     $blackUser = $black->getUser();
     // Don't rate games when one ore more player is not registered
     if (!$whiteUser || !$blackUser) {
         return;
     }
     if ($winner = $game->getWinner()) {
         $win = $winner->isWhite() ? -1 : 1;
     } else {
         $win = 0;
     }
     list($whiteElo, $blackElo) = $this->calculator->calculate($white->getElo(), $black->getElo(), $win);
     $white->setEloDiff($whiteEloDiff = $whiteElo - $white->getElo());
     $black->setEloDiff($blackEloDiff = $blackElo - $black->getElo());
     $this->eloUpdater->updateElo($whiteUser, $whiteUser->getElo() + $whiteEloDiff, $game);
     $this->eloUpdater->updateElo($blackUser, $blackUser->getElo() + $blackEloDiff, $game);
     $this->logger->notice($game, sprintf('Elo exchanged: %s', $whiteEloDiff));
 }