/** * @param BoardWalker $walker * @param MoveInterface $lastMove */ private function walkEnPassant(BoardWalker $walker, MoveInterface $lastMove = null) { $lastEnemyPiece = $lastMove ? $walker->getBoard()->getSquare($lastMove->getTo())->getPiece() : null; if ($lastMove === null || $lastEnemyPiece === null || $lastEnemyPiece->getType() !== PieceInterface::TYPE_PAWN) { return; } $leftToPosition = $walker->peek(BoardWalker::DIRECTION_LEFT, 1, null, true, false); $rightToPosition = $walker->peek(BoardWalker::DIRECTION_RIGHT, 1, null, true, false); if ($leftToPosition !== null) { if (abs(BoardHelper::getRowFromPosition($lastMove->getFrom()) - BoardHelper::getRowFromPosition($leftToPosition)) !== 2) { return; } if ($lastMove->getTo() === $leftToPosition) { // en passant left $walker->forwardLeft(1, false)->restart(); } } if ($rightToPosition !== null) { if (abs(BoardHelper::getRowFromPosition($lastMove->getFrom()) - BoardHelper::getRowFromPosition($rightToPosition)) !== 2) { return; } if ($lastMove->getTo() === $rightToPosition) { // en passant left $walker->forwardRight(1, false)->restart(); } } }
/** * @param MoveInterface $move * * @return string */ public static function toNotation(MoveInterface $move) { if (null === $move->getPiece()) { return ''; } $notation = ''; $piece = $move->getPiece(); $toLabel = strtolower($move->getToLabel()); $isPawn = $piece->getType() === PieceInterface::TYPE_PAWN; $pieceLetter = PieceDecorator::toLetter($piece); if (null !== ($capture = $move->getCapture())) { if ($isPawn) { $column = BoardHelper::getColumnFromPosition($move->getFrom()); $pieceLetter = BoardHelper::columnNumberToLetter($column); } $notation .= sprintf('%sx%s', $pieceLetter, $toLabel); if ($isPawn) { if ($move->getType() === MoveInterface::TYPE_CAPTURE_EN_PASSANT) { $notation .= 'e.p.'; } } return $notation; } if ($isPawn) { return $toLabel; } return sprintf('%s%s', $pieceLetter, $toLabel); }
/** * @param MoveInterface $move * @param bool $silentFailure */ public function add(MoveInterface $move, $silentFailure = false) { $piece = $move->getPiece(); if ($piece === null) { throw new \InvalidArgumentException('You can only add moves to the registry that has a piece connected to it'); } $moveData = $this->serialize($move->getTo()); $key = $this->getKey($move->getFrom(), $piece->getType(), $piece->getColor()); if (!array_key_exists($key, $this->moves)) { $this->moves[$key] = []; } foreach ($this->moves[$key] as $existingMoveData) { if ($existingMoveData === $moveData) { if ($silentFailure === true) { return; } throw new \InvalidArgumentException(sprintf('This move (%s) has already been registered with this key (%s)', $moveData, $existingMoveData)); } } $this->moves[$key][] = $moveData; $this->fresh = false; }
/** * @param MoveInterface $move * @param GameInterface $game * * @throws InvalidMoveException */ private static function validate(MoveInterface $move, GameInterface $game) { if ($game->hasFinished()) { throw new InvalidMoveException('Game has already finished'); } if (null === ($piece = $move->getPiece())) { if (null === ($piece = $game->getBoard()->getSquare($move->getFrom())->getPiece())) { var_export($game->getBoard()->getSquaresAsString()); throw new InvalidMoveException(sprintf('There must be a piece to move on that position: %s', $move->getFromLabel())); } } if ($game->getCurrentColor() !== $piece->getColor()) { throw new InvalidMoveException(sprintf('You can only move your own pieces: the %s on %s belongs to %s', $piece->getTypeLabel(), $move->getFromLabel(), $game->getOpposingPlayer()->getColor())); } }
/** * {@inheritdoc} */ public function mockMove(MoveInterface $move, BoardInterface $board) { $deepCopy = new DeepCopy(); /** @var BoardInterface $futureBoard */ $futureBoard = $deepCopy->copy($board); $fromSquare = $futureBoard->getSquare($move->getFrom()); $fromPiece = $fromSquare->getPiece(); $fromSquare->setPiece(null); $futureBoard->getSquare($move->getTo())->setPiece($fromPiece); return $futureBoard; }
/** * @param MoveInterface $move * * @return GameState */ private function createStateFromMove(MoveInterface $move) { if (!$move->getFrom()) { return null; } $gameState = new GameState(); $gameState->setFrom($move->getFrom()); $gameState->setTo($move->getTo()); $gameState->setPiece($move->getPiece()); $gameState->setCapture($move->getCapture()); $gameState->setMoveType($move->getType()); return $gameState; }