Ejemplo n.º 1
0
 private static function doRank(MoveInterface $move, GameInterface $game, MoveCalculatorInterface $moveCalculator, &$score = 1)
 {
     MoveHelper::enrich($move, $game);
     switch ($move->getType()) {
         case MoveInterface::TYPE_CAPTURE:
         case MoveInterface::TYPE_CAPTURE_EN_PASSANT:
             $score = 50;
             break;
     }
     $board = $game->getBoard();
     if ($moveCalculator->controlsCenter($move, $board)) {
         $score += 15;
     }
     if ($moveCalculator->avoidsCapture($move, $board)) {
         $score += 25;
     } elseif ($moveCalculator->causesCapture($move, $board)) {
         $score -= 25;
     }
     $opposingColor = $move->getPiece()->getColor() === Color::WHITE ? Color::BLACK : Color::WHITE;
     $mockedBoard = $moveCalculator->mockMove($move, $board);
     if ($moveCalculator->isChecked($opposingColor, $mockedBoard)) {
         if ($moveCalculator->isCheckmated($opposingColor, $mockedBoard)) {
             return 100;
         }
         return 99;
     }
     if ($score < 1) {
         return 1;
     }
     return $score;
 }
Ejemplo n.º 2
0
 /**
  * @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();
 }
Ejemplo n.º 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;
 }