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; }
/** * @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()); }
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(); }
public function isMyTurn() { return $this->game->getTurns() % 2 xor 'white' === $this->c; }
public function getIsMyTurn() { return $this->game->getTurns() % 2 xor 'white' === $this->color; }
/** * 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; }
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)); }