protected function getLastPiece(Player $player) { $pieces = PieceFilter::filterNotClass(PieceFilter::filterAlive($player->getPieces()), 'King'); return empty($pieces) ? null : $pieces[0]; }
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); }
/** * @depends testGameCreation */ public function testFilterNotClass(Entities\Game $game) { $piece1 = $game->getBoard()->getPieceByPos(1, 1); $piece2 = $game->getBoard()->getPieceByPos(2, 1); $this->assertSame(array($piece2), PieceFilter::filterNotClass(array($piece1, $piece2), 'Rook')); }
/** * @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; }