Exemplo n.º 1
0
 public function getAttackTargetKeys()
 {
     $keys = array();
     $mySquare = $this->board->getSquareByKey($this->getSquareKey());
     $x = $this->x;
     $y = $this->y;
     $dy = 'white' === $this->color ? 1 : -1;
     $_y = $y + $dy;
     foreach (array(-1, 1) as $dx) {
         $_x = $x + $dx;
         if ($_x < 1 || $_x > 8) {
             continue;
         }
         // eat
         $key = Board::posToKey($_x, $_y);
         if ($piece = $this->board->getPieceByKey($key)) {
             if ($piece->getColor() !== $this->color) {
                 $keys[] = $key;
             }
         }
         // en passant
         if (5 === $y || 4 === $y) {
             $opponentKey = Board::posToKey($_x, $y);
             if (($piece = $this->board->getPieceByKey($opponentKey)) && $piece instanceof Pawn && $piece->getColor() !== $this->color && $piece->getFirstMove() === $this->getPlayer()->getGame()->getTurns() - 1 && !$this->board->hasPieceByKey($key)) {
                 $keys[] = $key;
             }
         }
     }
     return $keys;
 }
Exemplo n.º 2
0
 public function getBasicTargetKeys()
 {
     $mySquare = $this->getSquare();
     $x = $mySquare->getX();
     $y = $mySquare->getY();
     $keys = array();
     $board = $this->getBoard();
     /**
      * That's ugly and could be done easily in a nicer way.
      * But I needed performance optimization.
      */
     for ($dx = -1; $dx < 2; $dx++) {
         $_x = $x + $dx;
         if ($_x > 0 && $_x < 9) {
             for ($dy = -1; $dy < 2; $dy++) {
                 if (0 === $dx && 0 === $dy) {
                     continue;
                 }
                 $_y = $y + $dy;
                 if ($_y > 0 && $_y < 9) {
                     $key = Board::posToKey($_x, $_y);
                     if (($piece = $board->getPieceByKey($key)) && $piece->getColor() === $this->color) {
                         continue;
                     }
                     $keys[] = $key;
                 }
             }
         }
     }
     return $keys;
 }
Exemplo n.º 3
0
 public function getBasicTargetKeys()
 {
     $mySquare = $this->getSquare();
     $x = $mySquare->getX();
     $y = $mySquare->getY();
     $keys = array();
     $board = $this->getBoard();
     /**
      * That's ugly and could be done easily in a nicer way.
      * But I needed performance optimization.
      */
     static $deltas = array(array(-1, 2), array(1, -2), array(2, -1), array(2, 1), array(1, 2), array(-1, -2), array(-2, 1), array(-2, -1));
     foreach ($deltas as $delta) {
         $_x = $x + $delta[0];
         $_y = $y + $delta[1];
         if ($_x > 0 && $_x < 9 && $_y > 0 && $_y < 9) {
             $key = Board::posToKey($_x, $_y);
             if (($piece = $board->getPieceByKey($key)) && $piece->getPlayer() === $this->player) {
                 continue;
             }
             $keys[] = $key;
         }
     }
     return $keys;
 }
Exemplo n.º 4
0
 public function getAttackTargetKeys()
 {
     $keys = array();
     $dy = 'white' === $this->color ? 1 : -1;
     $_y = $this->y + $dy;
     foreach (array(-1, 1) as $dx) {
         $_x = $this->x + $dx;
         if ($_x < 1 || $_x > 8) {
             continue;
         }
         $key = Board::posToKey($_x, $_y);
         $piece = $this->board->getPieceByKey($key);
         if (!$piece || $piece->getColor() !== $this->color) {
             $keys[] = $key;
         }
     }
     return $keys;
 }
Exemplo n.º 5
0
 public function getSquareKey()
 {
     return Board::posToKey($this->x, $this->y);
 }
Exemplo n.º 6
0
 public static function diffToMove(Game $game, $forsyth)
 {
     $moves = array('from' => array(), 'to' => array());
     $x = 1;
     $y = 8;
     $board = $game->getBoard();
     $forsyth = str_replace('/', '', preg_replace('#\\s*([\\w\\d/]+)\\s.+#i', '$1', $forsyth));
     for ($itForsyth = 0, $forsythLen = strlen($forsyth); $itForsyth < $forsythLen; $itForsyth++) {
         $letter = $forsyth[$itForsyth];
         $key = Board::posToKey($x, $y);
         if (is_numeric($letter)) {
             for ($x = $x, $max = $x + intval($letter); $x < $max; $x++) {
                 $_key = Board::posToKey($x, $y);
                 if (!$board->getSquareByKey($_key)->isEmpty()) {
                     $moves['from'][] = $_key;
                 }
             }
         } else {
             $color = ctype_lower($letter) ? 'black' : 'white';
             switch (strtolower($letter)) {
                 case 'p':
                     $class = 'Pawn';
                     break;
                 case 'r':
                     $class = 'Rook';
                     break;
                 case 'n':
                     $class = 'Knight';
                     break;
                 case 'b':
                     $class = 'Bishop';
                     break;
                 case 'q':
                     $class = 'Queen';
                     break;
                 case 'k':
                     $class = 'King';
                     break;
             }
             if ($piece = $board->getPieceByKey($key)) {
                 if ($class != $piece->getClass() || $color !== $piece->getColor()) {
                     $moves['to'][] = $key;
                 }
             } else {
                 $moves['to'][] = $key;
             }
             ++$x;
         }
         if ($x > 8) {
             $x = 1;
             --$y;
         }
     }
     if (empty($moves['from'])) {
         return null;
     } elseif (1 === count($moves['from']) && 1 === count($moves['to'])) {
         $from = $moves['from'][0];
         $to = $moves['to'][0];
     } elseif (2 === count($moves['from']) && 2 === count($moves['to'])) {
         if ($board->getPieceByKey($moves['from'][0])->isClass('King')) {
             $from = $moves['from'][0];
         } else {
             $from = $moves['from'][1];
         }
         if (in_array($board->getSquareByKey($moves['to'][0])->getX(), array(3, 7))) {
             $to = $moves['to'][0];
         } else {
             $to = $moves['to'][1];
         }
     } elseif (2 === count($moves['from']) && 1 === count($moves['to']) && $board->getPieceByKey($moves['from'][0])->isClass('Pawn') && $board->getPieceByKey($moves['from'][1])->isClass('Pawn') && !$board->hasPieceByKey($moves['to'][0])) {
         if ($moves['from'][0][0] === $moves['to'][0][0]) {
             $from = $moves['from'][1];
         } else {
             $from = $moves['from'][0];
         }
         $to = $moves['to'][0];
     } else {
         throw new \RuntimeException(sprintf('Forsyth:diffToMove game:%s, variant:%s, moves: %s, forsyth:%s', $game->getId(), $game->getVariantName(), str_replace("\n", " ", var_export($moves, true)), $forsyth));
     }
     return $from . ' ' . $to;
 }
Exemplo n.º 7
0
 /**
  * @depends testBoardCreation
  */
 public function testPosToKey(Board $board)
 {
     $this->assertEquals('a1', $board->posToKey(1, 1));
     $this->assertEquals('h8', $board->posToKey(8, 8));
     $this->assertEquals('b4', $board->posToKey(2, 4));
 }
Exemplo n.º 8
0
 public function diffToMove(Game $game, $forsythe)
 {
     $moves = array('from' => array(), 'to' => array());
     $x = 1;
     $y = 8;
     $board = $game->getBoard();
     $forsythe = str_replace('/', '', preg_replace('#\\s*([\\w\\d/]+)\\s.+#i', '$1', $forsythe));
     for ($itForsythe = 0, $forsytheLen = strlen($forsythe); $itForsythe < $forsytheLen; $itForsythe++) {
         $letter = $forsythe[$itForsythe];
         $key = Board::posToKey($x, $y);
         if (is_numeric($letter)) {
             for ($x = $x, $max = $x + intval($letter); $x < $max; $x++) {
                 $_key = Board::posToKey($x, $y);
                 if (!$board->getSquareByKey($_key)->isEmpty()) {
                     $moves['from'][] = $_key;
                 }
             }
         } else {
             $color = ctype_lower($letter) ? 'black' : 'white';
             switch (strtolower($letter)) {
                 case 'p':
                     $class = 'Pawn';
                     break;
                 case 'r':
                     $class = 'Rook';
                     break;
                 case 'n':
                     $class = 'Knight';
                     break;
                 case 'b':
                     $class = 'Bishop';
                     break;
                 case 'q':
                     $class = 'Queen';
                     break;
                 case 'k':
                     $class = 'King';
                     break;
             }
             if ($piece = $board->getPieceByKey($key)) {
                 if ($class != $piece->getClass() || $color !== $piece->getColor()) {
                     $moves['to'][] = $key;
                 }
             } else {
                 $moves['to'][] = $key;
             }
             ++$x;
         }
         if ($x > 8) {
             $x = 1;
             --$y;
         }
     }
     if (empty($moves['from'])) {
         return null;
     }
     // two pieces moved: it's a castle
     if (2 === count($moves['from'])) {
         if ($board->getPieceByKey($moves['from'][0])->isClass('King')) {
             $from = $moves['from'][0];
         } else {
             $from = $moves['from'][1];
         }
         if (in_array($board->getSquareByKey($moves['to'][0])->getX(), array(3, 7))) {
             $to = $moves['to'][0];
         } else {
             $to = $moves['to'][1];
         }
     } else {
         $from = $moves['from'][0];
         $to = $moves['to'][0];
     }
     return $from . ' ' . $to;
 }
Exemplo n.º 9
0
 /**
  * Add castling moves if available
  *
  * @return array the squares where the king can go
  **/
 protected function addCastlingSquares(King $king, array $squares)
 {
     $player = $king->getPlayer();
     $rooks = PieceFilter::filterNotMoved(PieceFilter::filterClass(PieceFilter::filterAlive($player->getPieces()), 'Rook'));
     if (empty($rooks)) {
         return $squares;
     }
     $opponentControlledKeys = $this->getPlayerControlledKeys($player->getOpponent(), true);
     foreach ($rooks as $rook) {
         $kingX = $king->getX();
         $kingY = $king->getY();
         $rookX = $rook->getX();
         $dx = $kingX > $rookX ? -1 : 1;
         $newKingX = 1 === $dx ? 7 : 3;
         $newRookX = 1 === $dx ? 6 : 4;
         $possible = true;
         // Unattacked
         $rangeMin = min($kingX, $newKingX);
         $rangeMax = min(8, max($kingX, $newKingX) + 1);
         for ($_x = $rangeMin; $_x !== $rangeMax; $_x++) {
             if (in_array(Board::posToKey($_x, $kingY), $opponentControlledKeys)) {
                 $possible = false;
                 break;
             }
         }
         // Unimpeded
         $rangeMin = min($kingX, $rookX, $newKingX, $newRookX);
         $rangeMax = min(8, max($kingX, $rookX, $newKingX, $newRookX) + 1);
         for ($_x = $rangeMin; $_x !== $rangeMax; $_x++) {
             if ($piece = $this->board->getPieceByKey(Board::posToKey($_x, $kingY))) {
                 if ($piece !== $king && $piece !== $rook) {
                     $possible = false;
                     break;
                 }
             }
         }
         if ($possible) {
             // If King moves one square or less (Chess variant)
             if (1 >= abs($kingX - $newKingX)) {
                 $newKingSquare = $rook->getSquare();
             } else {
                 $newKingSquare = $this->board->getSquareByPos($newKingX, $kingY);
             }
             $squares[] = $newKingSquare;
         }
     }
     return $squares;
 }