/** * Handle pawn promotion **/ protected function promotion(Pawn $pawn, $promotionClass) { $player = $pawn->getPlayer(); $this->board->remove($pawn); $player->removePiece($pawn); $fullClass = 'Bundle\\LichessBundle\\Document\\Piece\\' . $promotionClass; $new = new $fullClass($pawn->getX(), $pawn->getY()); $new->setBoard($player->getGame()->getBoard()); $player->addPiece($new); $this->board->add($new); $this->stack->addEvent(array('type' => 'promotion', 'pieceClass' => strtolower($promotionClass), 'key' => $new->getSquareKey())); }
public function getPiecePossibleMoves(Piece $piece) { $player = $piece->getPlayer(); $isKingAttacked = $this->isKingAttacked($player); $allOpponentPieces = PieceFilter::filterNotClass(PieceFilter::filterAlive($player->getOpponent()->getPieces()), 'King'); $king = $player->getKing(); $kingSquareKey = $king->getSquareKey(); $pieceOriginalX = $piece->getX(); $pieceOriginalY = $piece->getY(); $opponentPieces = PieceFilter::filterProjection($allOpponentPieces); //if we are not moving the king, and the king is not attacked, don't check pawns nor knights if (!$piece instanceof King && !$isKingAttacked) { $opponentPieces = PieceFilter::filterProjection($opponentPieces); } $squares = $this->board->keysToSquares($piece->getBasicTargetKeys()); if ($piece instanceof King && !$isKingAttacked && !$piece->hasMoved()) { $squares = $this->addCastlingSquares($piece, $squares); } foreach ($squares as $it => $square) { // kings move to its target so we update its position if ($piece instanceof King) { $kingSquareKey = $square->getKey(); } // kill opponent piece if ($killedPiece = $square->getPiece()) { $killedPiece->setIsDead(true); } $this->board->move($piece, $square->getX(), $square->getY()); foreach ($opponentPieces as $opponentPiece) { if (null !== $killedPiece && $opponentPiece->getIsDead()) { continue; } // if our king gets attacked if (in_array($kingSquareKey, $this->getPieceControlledKeys($opponentPiece, $piece instanceof King))) { // can't go here unset($squares[$it]); break; } } $this->board->move($piece, $pieceOriginalX, $pieceOriginalY); // if a piece has been killed, bring it back to life if ($killedPiece) { $killedPiece->setIsDead(false); $this->board->add($killedPiece); } } return $this->board->squaresToKeys($squares); }
/** * Handle pawn promotion **/ protected function promotion(Pawn $pawn, array $options) { $promotionClass = isset($options['promotion']) ? ucfirst($options['promotion']) : 'Queen'; if (!in_array($promotionClass, array('Queen', 'Knight', 'Bishop', 'Rook'))) { throw new \InvalidArgumentException('Bad promotion class: ' . $promotionClass); } $player = $pawn->getPlayer(); $this->board->remove($pawn); $player->removePiece($pawn); $fullClass = 'Bundle\\LichessBundle\\Entities\\Piece\\' . $promotionClass; $new = new $fullClass($pawn->getX(), $pawn->getY()); $new->setPlayer($player); $new->setBoard($player->getGame()->getBoard()); $player->addPiece($new); $this->board->add($new); if ($this->stack) { $this->stack->add(array('type' => 'promotion', 'pieceClass' => strtolower($promotionClass), 'key' => $new->getSquareKey())); } }
/** * @return array key => array keys */ public function getPlayerPossibleMoves(Player $player, $isKingAttacked = null) { $possibleMoves = array(); $isKingAttacked = null === $isKingAttacked ? $this->isKingAttacked($player) : $isKingAttacked; $allOpponentPieces = PieceFilter::filterAlive($player->getOpponent()->getPieces()); $attackOpponentPieces = PieceFilter::filterNotClass($allOpponentPieces, 'King'); $projectionOpponentPieces = PieceFilter::filterProjection($allOpponentPieces); $king = $player->getKing(); foreach (PieceFilter::filterAlive($player->getPieces()) as $piece) { $kingSquareKey = $king->getSquareKey(); $pieceOriginalX = $piece->getX(); $pieceOriginalY = $piece->getY(); $pieceClass = $piece->getClass(); //if we are not moving the king, and the king is not attacked, don't check pawns nor knights if ('King' === $pieceClass) { $opponentPieces = $allOpponentPieces; } elseif ($isKingAttacked) { $opponentPieces = $attackOpponentPieces; } else { $opponentPieces = $projectionOpponentPieces; } $squares = $this->board->keysToSquares($piece->getBasicTargetKeys()); foreach ($squares as $it => $square) { // king move to its target so we update its position if ('King' === $pieceClass) { $kingSquareKey = $square->getKey(); } // kill opponent piece if ($killedPiece = $square->getPiece()) { $killedPiece->setIsDead(true); } elseif ('Pawn' === $pieceClass && $square->getX() !== $pieceOriginalX) { $killedPiece = $square->getSquareByRelativePos(0, $player->isWhite() ? -1 : 1)->getPiece(); $killedPiece->setIsDead(true); } $this->board->move($piece, $square->getX(), $square->getY()); foreach ($opponentPieces as $opponentPiece) { if (null !== $killedPiece && $opponentPiece->getIsDead()) { continue; } // if our king gets attacked if (in_array($kingSquareKey, $opponentPiece->getAttackTargetKeys())) { // can't go here unset($squares[$it]); break; } } $this->board->move($piece, $pieceOriginalX, $pieceOriginalY); // if a piece has been killed, bring it back to life if ($killedPiece) { $killedPiece->setIsDead(false); $this->board->add($killedPiece); } } if ('King' === $pieceClass && !$isKingAttacked && !$piece->hasMoved()) { $squares = $this->addCastlingSquares($piece, $squares); } if (!empty($squares)) { $possibleMoves[$piece->getSquareKey()] = $this->board->squaresToKeys($squares); } } return $possibleMoves; }