Example #1
0
 /**
  * Transform a game to standard Forsyth Edwards Notation
  * http://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation
  */
 public static function export(Game $game, $positionOnly = false)
 {
     static $reverseClasses = array('Pawn' => 'p', 'Rook' => 'r', 'Knight' => 'n', 'Bishop' => 'b', 'Queen' => 'q', 'King' => 'k');
     $board = $game->getBoard();
     $emptySquare = 0;
     $forsyth = '';
     for ($y = 8; $y > 0; $y--) {
         for ($x = 1; $x < 9; $x++) {
             if ($piece = $board->getPieceByPosNoCheck($x, $y)) {
                 if ($emptySquare) {
                     $forsyth .= $emptySquare;
                     $emptySquare = 0;
                 }
                 $notation = $reverseClasses[$piece->getClass()];
                 if ('white' === $piece->getColor()) {
                     $notation = strtoupper($notation);
                 }
                 $forsyth .= $notation;
             } else {
                 ++$emptySquare;
             }
         }
         if ($emptySquare) {
             $forsyth .= $emptySquare;
             $emptySquare = 0;
         }
         $forsyth .= '/';
     }
     $forsyth = trim($forsyth, '/');
     if ($positionOnly) {
         return $forsyth;
     }
     // b ou w to indicate turn
     $forsyth .= ' ';
     $forsyth .= substr($game->getTurnColor(), 0, 1);
     // possibles castles
     $forsyth .= ' ';
     $hasCastle = false;
     $analyser = new Analyser($board);
     foreach ($game->getPlayers() as $player) {
         if ($analyser->canCastleKingSide($player)) {
             $hasCastle = true;
             $forsyth .= $player->isWhite() ? 'K' : 'k';
         }
         if ($analyser->canCastleQueenSide($player)) {
             $hasCastle = true;
             $forsyth .= $player->isWhite() ? 'Q' : 'q';
         }
     }
     if (!$hasCastle) {
         $forsyth .= '-';
     }
     // en passant
     $enPassant = '-';
     foreach (PieceFilter::filterClass(PieceFilter::filterAlive($game->getPieces()), 'Pawn') as $piece) {
         if ($piece->getFirstMove() === $game->getTurns() - 1) {
             $color = $piece->getPlayer()->getColor();
             $y = $piece->getY();
             if ($color === 'white' && 4 === $y || $color === 'black' && 5 === $y) {
                 $enPassant = Board::posToKey($piece->getX(), 'white' === $color ? $y - 1 : $y + 1);
                 break;
             }
         }
     }
     $forsyth .= ' ' . $enPassant;
     // Halfmove clock: This is the number of halfmoves since the last pawn advance or capture.
     // This is used to determine if a draw can be claimed under the fifty-move rule.
     $forsyth .= ' ' . $game->getHalfmoveClock();
     // Fullmove number: The number of the full move. It starts at 1, and is incremented after Black's move.
     $forsyth .= ' ' . $game->getFullMoveNumber();
     return $forsyth;
 }