diff --git a/FenParser0x88.php b/FenParser0x88.php index b3f58fc..a00a33c 100644 --- a/FenParser0x88.php +++ b/FenParser0x88.php @@ -393,9 +393,9 @@ class FenParser0x88 } if ($kingSideCastle - && !($this->cache['board'][$piece['s']+1]) - && !($this->cache['board'][$piece['s']+2]) - && ($this->cache['board'][$piece['s']+3]) + && !($this->cache['board'][$piece['s'] + 1]) + && !($this->cache['board'][$piece['s'] + 2]) + && ($this->cache['board'][$piece['s'] + 3]) && !strstr($protectiveMoves, Board0x88Config::$keySquares[$piece['s']]) && ($piece['s'] < 118 && !strstr($protectiveMoves, Board0x88Config::$keySquares[$piece['s'] + 1])) && ($piece['s'] < 117 && !strstr($protectiveMoves, Board0x88Config::$keySquares[$piece['s'] + 2])) @@ -405,11 +405,12 @@ class FenParser0x88 } if ($queenSideCastle && $piece['s'] - 2 != -1 - && !($this->cache['board'][$piece['s']-1]) - && !($this->cache['board'][$piece['s']-2]) - && !($this->cache['board'][$piece['s']-3]) - && ($this->cache['board'][$piece['s']-4]) - && !strstr($protectiveMoves, Board0x88Config::$keySquares[$piece['s']]) && !strstr($protectiveMoves, Board0x88Config::$keySquares[$piece['s'] - 1]) && !strstr($protectiveMoves, Board0x88Config::$keySquares[$piece['s'] - 2])) { + && !($this->cache['board'][$piece['s'] - 1]) + && !($this->cache['board'][$piece['s'] - 2]) + && !($this->cache['board'][$piece['s'] - 3]) + && ($this->cache['board'][$piece['s'] - 4]) + && !strstr($protectiveMoves, Board0x88Config::$keySquares[$piece['s']]) && !strstr($protectiveMoves, Board0x88Config::$keySquares[$piece['s'] - 1]) && !strstr($protectiveMoves, Board0x88Config::$keySquares[$piece['s'] - 2]) + ) { $paths[] = $piece['s'] - 2; } break; @@ -817,10 +818,30 @@ class FenParser0x88 } + private function getFromAndToByLongNotation($notation) + { + $notation = preg_replace('/[^a-h0-8]/si', '', $notation); + return array( + 'from' => substr($notation, 0, 2), + 'to' => substr($notation, 2, 2) + ); + + } + + public function getExtendedMoveInfo($move){ + $move = $this->getParsed($move); + + + + return $move; + } + + public function getParsed($move) { if (is_string($move)) $move = array('m' => $move); + if (isset($move['m'])) { if ($move['m'] == '--') { $this->fen = null; @@ -830,8 +851,13 @@ class FenParser0x88 'fen' => $this->getFen() ); } - $fromAndTo = $this->getFromAndToByNotation($move['m']); - }else{ + if (is_string($move['m']) && preg_match('/^[a-h][0-8][a-h][0-8]$/', $move['m'])) { + $fromAndTo = $this->getFromAndToByLongNotation($move['m']); + } else { + $fromAndTo = $this->getFromAndToByNotation($move['m']); + + } + } else { $fromAndTo = $move; } $this->makeMove($fromAndTo); @@ -979,15 +1005,14 @@ class FenParser0x88 // TODO some pgn files may not have correct notations for all moves. Example Nd7 which may be from b2 or f6. // this may cause problems later on in the game. Figure out a way to handle this. #if (count($foundPieces) === 2){ - #$ret['from'] = $foundPieces[1]; - #throw new Exception("Unable to decide which move to take for notation: ". $notation); + #$ret['from'] = $foundPieces[1]; + #throw new Exception("Unable to decide which move to take for notation: ". $notation); #} - if(!isset($ret['from'])){ + if (!isset($ret['from'])) { - - $msg = "Fen: ".$this->fen ."\ncolor: ". $color. "\nnotation: ". $notation."\nRank:". $fromRank. "\nFile:". $fromFile."\n". count($foundPieces).", ". implode(",", $foundPieces); + $msg = "Fen: " . $this->fen . "\ncolor: " . $color . "\nnotation: " . $notation . "\nRank:" . $fromRank . "\nFile:" . $fromFile . "\n" . count($foundPieces) . ", " . implode(",", $foundPieces); throw new Exception($msg); } $ret['from'] = Board0x88Config::$numberToSquareMapping[$ret['from']]; @@ -1074,8 +1099,22 @@ class FenParser0x88 private $notation; private $validMoves = null; + + function moveByLongNotation($notation){ + $fromAndTo = $this->getFromAndToByLongNotation($notation); + + $this->move($fromAndTo); + } + function move($move) { + + if(is_string($move) && strlen($move) == 4){ + $move = $this->getFromAndToByLongNotation($move); + }else if(is_string($move)){ + $move = $this->getFromAndToByNotation($move); + } + $this->fen = null; $this->validMoves = null; $this->piecesInvolved = $this->getPiecesInvolvedInMove($move); @@ -1092,6 +1131,8 @@ class FenParser0x88 } } + + } function setNewColor() @@ -1306,15 +1347,19 @@ class FenParser0x88 $move['to'] = Board0x88Config::$mapping[$move['to']]; $type = $this->cache['board'][$move['from']]; + + $ret = Board0x88Config::$notationMapping[$this->cache['board'][$move['from']]]; + + switch ($type) { case 0x01: case 0x09: if ($this->isEnPassantMove($move) || $this->cache['board'][$move['to']]) { - $ret += Board0x88Config::$fileMapping[$move['from'] & 15] + 'x'; + $ret .= Board0x88Config::$fileMapping[$move['from'] & 15] . 'x'; } - $ret += Board0x88Config::$fileMapping[$move['to'] & 15] + '' + Board0x88Config::$rankMapping[$move['to'] & 240]; + $ret .= Board0x88Config::$fileMapping[$move['to'] & 15] . '' . Board0x88Config::$rankMapping[$move['to'] & 240]; if (isset($move['promoteTo']) && $move['promoteTo']) { $numType = Board0x88Config::$typeToNumberMapping[$move['promoteTo']]; $ret .= '=' . Board0x88Config::$notationMapping[$numType]; @@ -1329,14 +1374,15 @@ class FenParser0x88 case 0x0E: case 0x0F: $config = $this->getValidMovesAndResult(); + $configMoves = $config['moves']; foreach ($configMoves as $square => $moves) { if ($square != $move['from'] && $this->cache['board'][$square] === $type) { - if (array_search($move['to'], $moves) >= 0) { + if (array_search($move['to'], $moves) !== FALSE) { if (($square & 15) != ($move['from'] & 15)) { - $ret += Board0x88Config::$fileMapping[$move['from'] & 15]; + $ret .= Board0x88Config::$fileMapping[$move['from'] & 15]; } else if (($square & 240) != ($move['from'] & 240)) { - $ret += Board0x88Config::$rankMapping[$move['from'] & 240]; + $ret .= Board0x88Config::$rankMapping[$move['from'] & 240]; } } } @@ -1345,7 +1391,8 @@ class FenParser0x88 if ($this->cache['board'][$move['to']]) { $ret .= 'x'; } - $ret .= Board0x88Config::$fileMapping[$move['to'] & 15] . '' . Board0x88Config::$rankMapping[$move['to'] & 240]; + $ret .= Board0x88Config::$fileMapping[$move['to'] & 15]; + $ret .= Board0x88Config::$rankMapping[$move['to'] & 240]; break; case 0x03: case 0x0B: @@ -1359,11 +1406,12 @@ class FenParser0x88 if ($this->cache['board'][$move['to']]) { $ret .= 'x'; } - $ret .= Board0x88Config::$fileMapping[$move['to'] & 15] + '' + Board0x88Config::$rankMapping[$move['to'] & 240]; + $ret .= Board0x88Config::$fileMapping[$move['to'] & 15] . '' . Board0x88Config::$rankMapping[$move['to'] & 240]; } break; } + return $ret; } @@ -1399,6 +1447,6 @@ class FenParser0x88 if ($emptyCounter) { $fen .= $emptyCounter; } - return $fen . " ". $this->getColorCode(). " ". $this->getCastle()." ". $this->fenParts['enPassant']." ". $this->getHalfMoves()." ". $this->getFullMoves(); + return $fen . " " . $this->getColorCode() . " " . $this->getCastle() . " " . $this->fenParts['enPassant'] . " " . $this->getHalfMoves() . " " . $this->getFullMoves(); } } diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..9f5c7a5 --- /dev/null +++ b/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "phpunit/phpunit" : "4.8.*" + } +} \ No newline at end of file diff --git a/composer.phar b/composer.phar new file mode 100755 index 0000000..85d2149 Binary files /dev/null and b/composer.phar differ diff --git a/test/ParserTest.php b/test/ParserTest.php index c3f9302..31d0ec2 100644 --- a/test/ParserTest.php +++ b/test/ParserTest.php @@ -7,7 +7,7 @@ * */ -require_once(__DIR__."/../../autoload.php"); +require_once(__DIR__."/../autoload.php"); class ParserTest extends PHPUnit_Framework_TestCase @@ -55,6 +55,59 @@ class ParserTest extends PHPUnit_Framework_TestCase $this->assertEquals('d6', $parser->getEnPassantSquare()); } + /** + * @test + */ + public function shouldSolveProblematicFen1(){ + $fen = '[Event "Bundesliga 2014/15"] +[Site "Solingen GER"] +[Date "2014.10.18"] +[Round "1"] +[White "Jakovenko, Dmitry"] +[Black "Navara, David"] +[Result "1/2-1/2"] +[ECO "D11"] +[WhiteElo "2747"] +[BlackElo "2718"] +[PlyCount "74"] +[EventDate "2014.10.18"] +[EventType "team"] +[WhiteTeam "SK Schwaebisch Hall"] +[BlackTeam "SV Muelheim Nord"] + + + +1. Nf3 d5 2. d4 Nf6 3. c4 c6 4. e3 Bg4 5. h3 Bxf3 6. Qxf3 e6 7. Nc3 Nbd7 8. Bd2 +Bb4 9. Bd3 O-O 10. a3 Bxc3 11. Bxc3 Re8 12. O-O e5 13. dxe5 Nxe5 14. Bxe5 Rxe5 +15. Rfd1 Qe7 16. cxd5 Rxd5 17. Bc4 Rdd8 18. Rxd8+ Rxd8 19. Rd1 g6 20. Rxd8+ +Qxd8 21. g4 h6 22. Qf4 Kg7 23. Kg2 Qe7 24. h4 c5 25. a4 b6 26. b3 Qb7+ 27. f3 +Qe7 28. e4 Nh7 29. h5 Nf8 30. Qb8 g5 31. Qc8 Ne6 32. Bxe6 Qxe6 33. Qxe6 fxe6 +34. e5 a6 35. Kf2 b5 36. axb5 axb5 37. Ke3 Kf7 1/2-1/2'; + + + $pgnParser = new PgnParser(); + $pgnParser->setPgnContent($fen); + $game = $pgnParser->getFirstGame(); + + $parser = new FenParser0x88(); + $parser->newGame(); + $parser->move("g1f3"); + $notation = $parser->getNotation(); + + + + $this->assertEquals("Nf3", $notation); + + + $parser = new FenParser0x88(); + $parser->newGame(); + $parser->move("Nf3"); + $notation = $parser->getNotation(); + $this->assertEquals("Nf3", $notation); + + + } + /** * @test */