Example #1
0
 protected function assertGamePgn($pgn)
 {
     $dumper = new PgnDumper();
     $dumped = $dumper->dumpGame($this->game);
     $pgn = str_replace('%date%', date('Y.m.d'), $pgn);
     $this->assertEquals($pgn, $dumped);
 }
Example #2
0
 /**
  * Move a piece on the board
  * Performs several validation before applying the move
  *
  * @param mixed $notation Valid algebraic notation (e.g. "a2 a4")
  * @return string PGN notation of the move
  */
 public function move($notation, array $options = array())
 {
     list($fromKey, $toKey) = explode(' ', $notation);
     if (!$fromKey || !$toKey) {
         throw new \InvalidArgumentException(sprintf('Manipulator:move game:%s, Invalid internal move notation "%s"', $this->game->getId(), $notation));
     }
     if (!($from = $this->board->getSquareByKey($fromKey))) {
         throw new \InvalidArgumentException(sprintf('Manipulator:move game:%s, Square ' . $fromKey . ' does not exist', $this->game->getId()));
     }
     if (!($to = $this->board->getSquareByKey($toKey))) {
         throw new \InvalidArgumentException(sprintf('Manipulator:move game:%s, Square ' . $toKey . ' does not exist', $this->game->getId()));
     }
     if (!($piece = $from->getPiece())) {
         throw new \InvalidArgumentException(sprintf('Manipulator:move game:%s, No piece on ' . $from, $this->game->getId()));
     }
     $player = $piece->getPlayer();
     if (!$player->isMyTurn()) {
         throw new \LogicException(sprintf('Manipulator:move game:%s, Can not play ' . $from . ' ' . $to . ' - Not ' . $piece->getColor() . ' player turn', $this->game->getId()));
     }
     $pieceClass = $piece->getClass();
     $isPlayerKingAttacked = $this->analyser->isKingAttacked($player);
     $playerPossibleMoves = $this->analyser->getPlayerPossibleMoves($player, $isPlayerKingAttacked);
     $possibleMoves = isset($playerPossibleMoves[$fromKey]) ? $playerPossibleMoves[$fromKey] : false;
     if (!$possibleMoves) {
         throw new \LogicException(sprintf('Manipulator:move game:%s, %s can not move', $this->game->getId(), $piece));
     }
     if (!in_array($toKey, $possibleMoves)) {
         throw new \LogicException(sprintf('Manipulator:move game:%s, %s can not go to ' . $to . ' (' . implode(',', $possibleMoves) . ')', $this->game->getId(), $piece));
     }
     // killed?
     $killed = $to->getPiece();
     // castling?
     $isCastling = false;
     if ('King' === $pieceClass) {
         // standard castling
         if (1 < abs($from->getX() - $to->getX())) {
             $isCastling = true;
         } elseif ($killed && $killed->getColor() === $piece->getColor()) {
             $isCastling = true;
             $killed = null;
         }
     }
     // promotion?
     if ('Pawn' === $pieceClass && $to->getY() === ($player->isWhite() ? 8 : 1)) {
         $isPromotion = true;
         $promotionClass = isset($options['promotion']) ? ucfirst($options['promotion']) : 'Queen';
         if (!in_array($promotionClass, array('Queen', 'Knight', 'Bishop', 'Rook'))) {
             throw new \InvalidArgumentException(sprintf('Manipulator:move game:%s, Bad promotion class: ' . $promotionClass, $this->game->getId()));
         }
         $options['promotion'] = $promotionClass;
     } else {
         $isPromotion = false;
     }
     // enpassant?
     $isEnPassant = 'Pawn' === $pieceClass && $to->getX() !== $from->getX() && !$killed;
     $pgnDumper = new PgnDumper();
     $pgn = $pgnDumper->dumpMove($this->game, $piece, $from, $to, $playerPossibleMoves, $killed, $isCastling, $isPromotion, $isEnPassant, $options);
     $this->stack->addEvent(array('type' => 'move', 'from' => $from->getKey(), 'to' => $to->getKey(), 'color' => $piece->getColor()));
     if ($isCastling) {
         $this->castle($piece, $to);
     } else {
         if ($killed) {
             $killed->setIsDead(true);
             $this->board->remove($killed);
         }
         $this->board->move($piece, $to->getX(), $to->getY());
         if (null === $piece->getFirstMove()) {
             $piece->setFirstMove($this->game->getTurns());
         }
     }
     if ($isPromotion) {
         $this->promotion($piece, $options['promotion']);
     }
     if ($isEnPassant) {
         $this->enpassant($piece, $to);
     }
     // When an irreversible event happens,
     // we can safely clear the game position hashes
     if ($killed || $isPromotion || $isCastling || 'Pawn' === $pieceClass) {
         $this->game->clearPositionHashes();
     }
     return $pgn;
 }