-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Issue/696 convert an entire game into a chess signal (#701)
* Implemented Chess\SanSignal * Implemented Chess\SanTrait * Refactored Chess\SanHeuristics * Refactored Chess\SanSignal * Refactored Chess\SanHeuristics * Refactored Chess\SanTrait * Wording * Refactored Chess\SanSignal * Wording * Updated Chess\SanSignal * Added test * Updated tests
- Loading branch information
1 parent
af9daa2
commit 7e250b1
Showing
4 changed files
with
211 additions
and
118 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
<?php | ||
|
||
namespace Chess; | ||
|
||
use Chess\Function\AbstractFunction; | ||
use Chess\Play\SanPlay; | ||
use Chess\Variant\AbstractBoard; | ||
use Chess\Variant\Classical\PGN\Move; | ||
use Chess\Variant\Classical\PGN\AN\Color; | ||
|
||
/** | ||
* SAN Signal | ||
* | ||
* A signal encoding the continuous oscillations of a chessboard. | ||
*/ | ||
class SanSignal extends SanPlay | ||
{ | ||
use SanTrait; | ||
|
||
/** | ||
* The signal. | ||
* | ||
* @var array | ||
*/ | ||
public array $signal = []; | ||
|
||
/** | ||
* @param \Chess\Function\AbstractFunction $function | ||
* @param string $movetext | ||
* @param \Chess\Variant\AbstractBoard $board | ||
*/ | ||
public function __construct( | ||
AbstractFunction $function, | ||
string $movetext, | ||
AbstractBoard $board | ||
) { | ||
parent::__construct($movetext, $board); | ||
|
||
$this->result[] = array_fill(0, count($function->names()), 0); | ||
$component = []; | ||
|
||
foreach ($this->sanMovetext->moves as $val) { | ||
if ($val !== Move::ELLIPSIS) { | ||
if ($this->board->play($this->board->turn, $val)) { | ||
foreach ($function->names() as $val) { | ||
$item = $this->item(EvalFactory::create( | ||
$function, | ||
$val, | ||
$this->board | ||
)); | ||
$component[] = $item[Color::W] - $item[Color::B]; | ||
} | ||
$this->result[] = $component; | ||
$component = []; | ||
} | ||
} | ||
} | ||
|
||
for ($i = 0; $i < count($this->result[0]); $i++) { | ||
$this->balance[$i] = $this->normalize(-1, 1, array_column($this->result, $i)); | ||
} | ||
|
||
for ($i = 0; $i < count($this->result[0]); $i++) { | ||
$this->signal[$i] = round(array_sum(array_column($this->balance, $i)), 2); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
<?php | ||
|
||
namespace Chess; | ||
|
||
use Chess\Eval\AbstractEval; | ||
use Chess\Eval\InverseEvalInterface; | ||
use Chess\Variant\Classical\PGN\AN\Color; | ||
|
||
trait SanTrait | ||
{ | ||
/** | ||
* Continuous oscillations. | ||
* | ||
* @var array | ||
*/ | ||
public array $result = []; | ||
|
||
/** | ||
* The balanced normalized result. | ||
* | ||
* @var array | ||
*/ | ||
public array $balance = []; | ||
|
||
/** | ||
* Calculates an item. | ||
* | ||
* @param \Chess\Eval\AbstractEval $eval | ||
* @return array | ||
*/ | ||
protected function item(AbstractEval $eval): array | ||
{ | ||
$result = $eval->result; | ||
|
||
if (is_array($result[Color::W])) { | ||
if ($eval instanceof InverseEvalInterface) { | ||
$item = [ | ||
Color::W => count($result[Color::B]), | ||
Color::B => count($result[Color::W]), | ||
]; | ||
} else { | ||
$item = [ | ||
Color::W => count($result[Color::W]), | ||
Color::B => count($result[Color::B]), | ||
]; | ||
} | ||
} else { | ||
if ($eval instanceof InverseEvalInterface) { | ||
$item = [ | ||
Color::W => $result[Color::B], | ||
Color::B => $result[Color::W], | ||
]; | ||
} else { | ||
$item = $result; | ||
} | ||
} | ||
|
||
return $item; | ||
} | ||
|
||
/** | ||
* Normalizes an array of values. | ||
* | ||
* @param int $newMin | ||
* @param int $newMax | ||
* @param array $values | ||
* @return array | ||
*/ | ||
protected function normalize(int $newMin, int $newMax, array $values): array | ||
{ | ||
$min = min($values); | ||
$max = max($values); | ||
|
||
foreach ($values as $key => $val) { | ||
if ($val > 0) { | ||
$values[$key] = round($values[$key] * $newMax / $max, 2); | ||
} elseif ($val < 0) { | ||
$values[$key] = round($values[$key] * $newMin / $min, 2); | ||
} else { | ||
$values[$key] = 0; | ||
} | ||
} | ||
|
||
return $values; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<?php | ||
|
||
namespace Chess\Tests\Unit; | ||
|
||
use Chess\SanSignal; | ||
use Chess\Function\FastFunction; | ||
use Chess\Play\SanPlay; | ||
use Chess\Tests\AbstractUnitTestCase; | ||
use Chess\Variant\Classical\Board; | ||
|
||
class SanSignalTest extends AbstractUnitTestCase | ||
{ | ||
static private FastFunction $function; | ||
|
||
public static function setUpBeforeClass(): void | ||
{ | ||
self::$function = new FastFunction(); | ||
} | ||
|
||
/** | ||
* @test | ||
*/ | ||
public function e4_d5_exd5_Qxd5() | ||
{ | ||
$expectedBalance = [ 0, 1.0, 0.25, 0.50, -1.0 ]; | ||
$expectedSignal = [ 0.0, 2.0, -1.67, -0.16, -5.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ]; | ||
|
||
$movetext = '1.e4 d5 2.exd5 Qxd5'; | ||
|
||
$sanSignal = new SanSignal(self::$function, $movetext, new Board()); | ||
|
||
$this->assertEquals($expectedBalance, $sanSignal->balance[3]); | ||
$this->assertEquals($expectedSignal, $sanSignal->signal); | ||
} | ||
|
||
/** | ||
* @test | ||
*/ | ||
public function A59() | ||
{ | ||
$expectedSignal = [ 0.0, 2.5, 0.77, 1.01, 1.31, 1.4, 1.69, 3.52, 3.03, 2.77, 0.0, 1.85, 0.17, 0.88, -2.13, 3.42, 2.07, 2.24, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ]; | ||
|
||
$A59 = file_get_contents(self::DATA_FOLDER.'/sample/A59.pgn'); | ||
|
||
$sanSignal = new SanSignal(self::$function, $A59, new Board()); | ||
|
||
$this->assertEquals($expectedSignal, $sanSignal->signal); | ||
} | ||
} |