/** * @depends testGetBoard */ public function testGetBasicTargetSquaresSecondMove(Board $board) { $piece = $board->getPieceByKey('b1'); $piece->setX(3); $piece->setY(4); $board->compile(); $expected = array('a3', 'a5', 'b6', 'd6', 'e5', 'e3'); $this->assertSquareKeys($expected, $piece->getBasicTargetKeys()); }
/** * @depends testGetBoard */ public function testGetBasicTargetSquaresSecondMove(Board $board) { $piece = $board->getPieceByKey('d1'); $piece->setX(3); $piece->setY(4); $board->compile(); $expected = array('b3', 'b5', 'a6', 'd5', 'e6', 'f7', 'd3', 'a4', 'b4', 'd4', 'e4', 'f4', 'g4', 'h4', 'c3', 'c5', 'c6', 'c7'); $this->assertSquareKeys($expected, $piece->getBasicTargetKeys()); }
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; }
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; }
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; }
protected function getCastleRookInDirection(Player $player, $dx) { $king = $player->getKing(); if ($king->hasMoved()) { return null; } for ($x = $king->getX() + $dx; $x < 9 && $x > 0; $x += $dx) { if ($piece = $this->board->getPieceByPos($x, $king->getY())) { if ('Rook' === $piece->getClass() && !$piece->hasMoved() && $piece->getColor() === $king->getColor()) { return $piece; } } } }
/** * Handle castling **/ protected function castling(King $king, Square $to) { if (7 === $to->getX()) { $rookSquare = $to->getSquareByRelativePos(1, 0); $newRookSquare = $to->getSquareByRelativePos(-1, 0); } else { $rookSquare = $to->getSquareByRelativePos(-2, 0); $newRookSquare = $to->getSquareByRelativePos(1, 0); } $rook = $rookSquare->getPiece(); $this->board->move($rook, $newRookSquare->getX(), $newRookSquare->getY()); $rook->setFirstMove($this->game->getTurns()); if ($this->stack) { $this->stack->add(array('type' => 'castling', 'from' => $rookSquare->getKey(), 'to' => $newRookSquare->getKey())); } }
/** * @depends testGetBoard */ public function testGetBasicTargetSquaresEnPassant(Board $board) { $board->getGame()->setTurns(10); $piece = $board->getPieceByKey('f2'); $piece->setY('5'); $piece->setFirstMove(1); $board->getPieceByKey('g7')->setY(5); $board->getPieceByKey('g7')->setFirstMove(9); $board->compile(); $expected = array('f6'); $this->assertSquareKeys($expected, $piece->getBasicTargetKeys()); }
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; }
/** * Handle castling **/ protected function castle(King $king, Square $to) { $isKingSide = $this->isCastleKingSide($king, $to); $y = $king->getY(); if ($isKingSide) { $rook = $this->analyser->getCastleRookKingSide($king->getPlayer()); $newRookSquare = $this->board->getSquareByPos(6, $y); $newKingSquare = $this->board->getSquareByPos(7, $y); } else { $rook = $this->analyser->getCastleRookQueenSide($king->getPlayer()); $newRookSquare = $this->board->getSquareByPos(4, $y); $newKingSquare = $this->board->getSquareByPos(3, $y); } if (!$rook) { throw new \LogicException(sprintf('No rook for castle on %s side, king %s to %s', $isKingSide ? 'King' : 'Queen', $king->getSquareKey(), $to->getKey())); } $kingSquare = $king->getSquare(); $rookSquare = $rook->getSquare(); $this->board->castle($king, $rook, $newKingSquare->getX(), $newRookSquare->getX()); $king->setFirstMove($this->game->getTurns()); $rook->setFirstMove($this->game->getTurns()); $this->stack->addEvent(array('type' => 'castling', 'king' => array($kingSquare->getKey(), $newKingSquare->getKey()), 'rook' => array($rookSquare->getKey(), $newRookSquare->getKey()), 'color' => $king->getColor())); }
/** * @depends testBoardCreation */ public function testDump(Board $board) { $expected = <<<EOF rnbqkbnr pppppppp PPPPPPPP RNBQKBNR EOF; $this->assertEquals("\n" . Generator::fixVisualBlock($expected) . "\n", $board->dump()); }
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; }
public function getSquareKey() { return Board::posToKey($this->x, $this->y); }
/** * @depends testBoardCreation */ public function testDump(Board $board) { $expected = <<<EOF rnbqkbnr pppppppp PPPPPPPP RNBQKBNR EOF; $this->assertEquals($expected, $board->dump()); }
protected function canCastle(King $king, $relativeX) { $_x = $king->getX() + $relativeX; return $_x > 0 && $_x < 9 && !$king->hasMoved() && ($rook = $this->board->getSquareByPos($king->getX() + $relativeX, $king->getY())->getPiece()) && ($rook->isClass('Rook') && !$rook->hasMoved()); }
public function extractPieces() { $pieces = array(); if (!empty($this->ps)) { foreach (explode(' ', $this->ps) as $p) { $pos = Board::keyToPos(Board::piotrToKey($p[0])); $class = Piece::letterToClass(strtolower($p[1])); $piece = new Piece($pos[0], $pos[1], $class); if (ctype_upper($p[1])) { $piece->setIsDead(true); } $pieces[] = $piece; } } $this->setPieces($pieces); }
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; }