/**
  * @param string        $notation
  * @param GameInterface $game
  * @param array         $parsed
  *
  * @return int
  *
  * @throws InvalidNotationException
  */
 private function parseFrom($notation, GameInterface $game, array $parsed)
 {
     $enPassant = false;
     $capture = false;
     switch ($parsed['piece_type']) {
         case PieceInterface::TYPE_PAWN:
             if (substr($notation, -4) === 'e.p.') {
                 $enPassant = true;
             } elseif (substr($notation, 1, 1) === 'x') {
                 // calculate 'from' for capture by pawn (diagonally)
                 $capture = true;
             } else {
                 // calculate 'from' for forward move by pawn
             }
             break;
         default:
             // non-pawn calculation, depends on type
             break;
     }
     $finalMove = null;
     $criteria = ['piece_color' => $parsed['color'], 'piece_type' => $parsed['piece_type']];
     if (strlen($notation) > 3 && in_array(substr($notation, 1, 1), ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])) {
         $criteria['column'] = BoardHelper::columnLetterToNumber(substr($notation, 1, 1));
     }
     $possiblePieceMoves = $this->moveCalculator->possibleMovesTo($parsed['to'], $game->getBoard(), $criteria);
     foreach ($possiblePieceMoves as $move) {
         MoveHelper::enrich($move, $game);
         if ($enPassant === true && $move->getType() !== MoveInterface::TYPE_CAPTURE_EN_PASSANT) {
             continue;
         } elseif ($capture === true && $move->getType() !== MoveInterface::TYPE_CAPTURE) {
             continue;
         }
         if ($finalMove !== null) {
             throw new InvalidNotationException(sprintf('Multiple moves found starting from %s and ending on %s, you should make your notation more specific (criteria: %s)', $finalMove->getFromLabel(), $finalMove->getToLabel(), json_encode($criteria)));
         }
         $finalMove = $move;
     }
     if ($finalMove === null) {
         throw new InvalidNotationException(sprintf('There are no moves to make to this position: %s (criteria: %s)', $parsed['to'], json_encode($criteria, true)));
     }
     return $finalMove->getFrom();
 }
 /**
  * @param int   $colorToMove
  * @param Board $board
  *
  * @return array
  */
 private function getSimplifiedActualMoves($colorToMove, Board $board)
 {
     $moves = [];
     $moveCalculator = new MoveCalculator();
     foreach ($moveCalculator->possibleMovesBy($colorToMove, $board) as $actualMove) {
         $moves[] = [$actualMove->getFrom(), $actualMove->getTo()];
     }
     return $moves;
 }
Exemple #3
0
 /**
  * {@inheritdoc}
  */
 public function doEngineMove(MoveCalculator $moveCalculator)
 {
     $currentPlayer = $this->getCurrentPlayer();
     if ($currentPlayer->isHuman()) {
         throw new \LogicException('Can\\t make an engine-move with a human player');
     }
     $possibleMoves = $moveCalculator->possibleMovesBy($currentPlayer->getColor(), $this->getBoard());
     if (empty($possibleMoves)) {
         throw new \RuntimeException('Failed to find a move for the engine... probably because this scenario wasn\'t worked out yet');
     }
     $highestRankingMove = MoveRanker::best($possibleMoves, $this, $moveCalculator);
     MoveHelper::apply($highestRankingMove, $this);
     $this->addState($this->createStateFromMove($highestRankingMove));
     return $highestRankingMove;
 }