/** * {@inheritdoc} */ public function possibleCapturesBy($color, BoardInterface $board) { $moves = []; $criteria = ['piece_color' => $color]; foreach ($board->getSquaresBy($criteria) as $square) { $moves = array_merge($moves, $this->possibleCapturesFrom($square->getPosition(), $board)); } return $moves; }
/** * {@inheritdoc} */ public function __construct(PlayerInterface $whitePlayer, PlayerInterface $blackPlayer, BoardInterface $board, $id = null) { if ($whitePlayer->getColor() !== Color::WHITE) { throw new \LogicException("Given white player's PlayerInterface should have a white color"); } if ($blackPlayer->getColor() !== Color::BLACK) { throw new \LogicException("Given black player's PlayerInterface should have a black color"); } $board->setGame($this); $this->whitePlayer = $whitePlayer; $this->blackPlayer = $blackPlayer; $this->board = $board; $this->id = $id ?: uniqid(); $this->states = new ArrayCollection(); }
/** * @param BoardInterface $board * @param bool $flipped * * @return string */ public static function toAscii(BoardInterface $board, $flipped = false) { $squaresByRow = $board->getIndexedSquares('row'); $ascii = ''; if ($flipped !== true) { $squaresByRow = array_reverse($squaresByRow, true); } $previousRow = null; foreach ($squaresByRow as $row => $squares) { if ($previousRow !== $row) { if ($previousRow !== null) { $ascii .= "\n"; } $ascii .= sprintf('%d ║', $row); } /** @var Square[] $squares */ foreach ($squares as $square) { if (null !== ($piece = $square->getPiece())) { $ascii .= PieceDecorator::toAscii($piece); } else { $ascii .= '…'; } $ascii .= ' '; } $ascii = rtrim($ascii); $previousRow = $row; } $ascii .= "\n"; $columnLabels = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']; $ascii .= ' ╚' . str_repeat('═', count($columnLabels) * 2 - 1) . "\n"; $ascii .= ' '; foreach ($columnLabels as $columnLabel) { $ascii .= $columnLabel . ' '; } $ascii .= "\n"; return $ascii; }
/** * @param int $direction The direction to step into * @param int $jumps The number of jumps to make in this direction * @param int|null $startingPosition * @param bool $ignoreCapture * * @return int|null The expected position, or null if the move is not possible * * @throws \InvalidArgumentException */ public function peek($direction, $jumps = 1, $startingPosition = null, $ignoreCapture = false, $requireAttack = false) { $newPosition = null; if ($startingPosition !== null) { $column = BoardHelper::getColumnFromPosition($startingPosition); $row = BoardHelper::getRowFromPosition($startingPosition); } else { $column = $this->getColumn(); $row = $this->getRow(); } switch ($direction) { case self::DIRECTION_FORWARD: if ($this->color === Color::WHITE) { $newRow = $this->formatNumber($row + $jumps); } else { $newRow = $this->formatNumber($row - $jumps); } if ($newRow !== null) { $newPosition = intval($column . $newRow); } break; case self::DIRECTION_FORWARDRIGHT: if ($this->color === Color::WHITE) { $newColumn = $this->formatNumber($column + $jumps); $newRow = $this->formatNumber($row + $jumps); } else { $newColumn = $this->formatNumber($column - $jumps); $newRow = $this->formatNumber($row - $jumps); } if ($newColumn !== null && $newRow !== null) { $newPosition = intval($newColumn . $newRow); } break; case self::DIRECTION_RIGHT: if ($this->color === Color::WHITE) { $newColumn = $this->formatNumber($column + $jumps); } else { $newColumn = $this->formatNumber($column - $jumps); } if ($newColumn !== null) { $newPosition = intval($newColumn . $row); } break; case self::DIRECTION_BACKWARDRIGHT: if ($this->color === Color::WHITE) { $newColumn = $this->formatNumber($column + $jumps); $newRow = $this->formatNumber($row - $jumps); } else { $newColumn = $this->formatNumber($column - $jumps); $newRow = $this->formatNumber($row + $jumps); } if ($newColumn !== null && $newRow !== null) { $newPosition = intval($newColumn . $newRow); } break; case self::DIRECTION_BACKWARD: if ($this->color === Color::WHITE) { $newRow = $this->formatNumber($row - $jumps); } else { $newRow = $this->formatNumber($row + $jumps); } if ($newRow !== null) { $newPosition = intval($column . $newRow); } break; case self::DIRECTION_BACKWARDLEFT: if ($this->color === Color::WHITE) { $newColumn = $this->formatNumber($column - $jumps); $newRow = $this->formatNumber($row - $jumps); } else { $newColumn = $this->formatNumber($column + $jumps); $newRow = $this->formatNumber($row + $jumps); } if ($newColumn !== null && $newRow !== null) { $newPosition = intval($newColumn . $newRow); } break; case self::DIRECTION_LEFT: if ($this->color === Color::WHITE) { $newColumn = $this->formatNumber($column - $jumps); } else { $newColumn = $this->formatNumber($column + $jumps); } if ($newColumn !== null) { $newPosition = intval($newColumn . $row); } break; case self::DIRECTION_FORWARDLEFT: if ($this->color === Color::WHITE) { $newColumn = $this->formatNumber($column - $jumps); $newRow = $this->formatNumber($row + $jumps); } else { $newColumn = $this->formatNumber($column + $jumps); $newRow = $this->formatNumber($row - $jumps); } if ($newColumn !== null && $newRow !== null) { $newPosition = intval($newColumn . $newRow); } break; default: throw new \InvalidArgumentException(sprintf('Unknown direction to calculate: %s', $direction)); } if ($ignoreCapture !== true && $newPosition !== null) { $toPiece = $this->board->getSquare($newPosition)->getPiece(); if (null !== $toPiece) { if ($toPiece->getColor() === $this->getColor()) { // own piece, can't capture return null; } } elseif ($requireAttack === true) { return null; } } return $newPosition; }
/** * @param BoardInterface $board * @param int $color * * @return int */ public static function getKingPosition(BoardInterface $board, $color) { $kingSquares = $board->getSquaresBy(['piece_type' => PieceInterface::TYPE_KING, 'piece_color' => $color]); if (count($kingSquares) !== 1) { throw new \RuntimeException(sprintf('There should always be one king of a given color on the board, found %d', count($kingSquares))); } return reset($kingSquares)->getPosition(); }
/** * @param BoardInterface $board * * @return array */ private function getExpectedBoardArray(BoardInterface $board) { $squares = []; foreach ($board->getSquares() as $square) { $squares[$square->getPosition()] = ['position' => $square->getPosition(), 'color' => $square->getColor(), 'piece' => $this->getExpectedPieceArray($square->getPiece())]; } return ['squares' => $squares]; }