mirror of
https://github.com/sigmasternchen/php-chess
synced 2025-03-14 23:58:53 +00:00
feat: Initial commit + Position & FieldBitMap classes
This commit is contained in:
commit
85fa12c08f
8 changed files with 1840 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
vendor/
|
20
composer.json
Normal file
20
composer.json
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"name": "overflowerror/php-chess",
|
||||||
|
"description": "description",
|
||||||
|
"minimum-stability": "stable",
|
||||||
|
"license": "MIT",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "overflowerror",
|
||||||
|
"email": "email@example.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^10.5"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Game\\": "./src/Game/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1632
composer.lock
generated
Normal file
1632
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
12
phpunit.xml
Normal file
12
phpunit.xml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<phpunit bootstrap="./vendor/autoload.php"
|
||||||
|
displayDetailsOnTestsThatTriggerDeprecations="true"
|
||||||
|
displayDetailsOnTestsThatTriggerErrors="true"
|
||||||
|
displayDetailsOnTestsThatTriggerNotices="true"
|
||||||
|
displayDetailsOnTestsThatTriggerWarnings="true">
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="The project's test suite">
|
||||||
|
<directory>./tests</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
</phpunit>
|
71
src/Game/FieldBitMap.php
Normal file
71
src/Game/FieldBitMap.php
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Game;
|
||||||
|
|
||||||
|
if (gettype(2147483648) == "double") {
|
||||||
|
die("need 64 bit integers");
|
||||||
|
}
|
||||||
|
|
||||||
|
class FieldBitMap {
|
||||||
|
private int $map = 0;
|
||||||
|
|
||||||
|
public function __construct(array|int $argument) {
|
||||||
|
if (gettype($argument) == "array") {
|
||||||
|
foreach ($argument as $position) {
|
||||||
|
$this->add($position);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->map = $argument;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBitForPosition(Position $position): int {
|
||||||
|
return $position->file * 8 + $position->rank;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function add(Position $position): void {
|
||||||
|
if ($position->isValid()) {
|
||||||
|
$this->map |= 1 << $this->getBitForPosition($position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function intersect(FieldBitMap $map): FieldBitMap {
|
||||||
|
return new FieldBitMap($this->map & $map->map);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function union(FieldBitMap $map): FieldBitMap {
|
||||||
|
return new FieldBitMap($this->map | $map->map);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isEmpty(): bool {
|
||||||
|
return $this->map == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function has(Position $position): bool {
|
||||||
|
return ($this->map & (1 << $this->getBitForPosition($position))) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPositions(): array {
|
||||||
|
$result = [];
|
||||||
|
|
||||||
|
for ($i = 0; $i < 64; $i++) {
|
||||||
|
if ($this->map & (1 << $i)) {
|
||||||
|
$result[] = new Position(floor($i / 8), $i % 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMap(): int {
|
||||||
|
return $this->map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function full(): FieldBitMap {
|
||||||
|
return new FieldBitMap(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function empty(): FieldBitMap {
|
||||||
|
return new FieldBitMap(0);
|
||||||
|
}
|
||||||
|
}
|
23
src/Game/Position.php
Normal file
23
src/Game/Position.php
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Game;
|
||||||
|
|
||||||
|
class Position {
|
||||||
|
public int $file;
|
||||||
|
public int $rank;
|
||||||
|
|
||||||
|
public function __construct($file, $rank) {
|
||||||
|
$this->rank = $rank;
|
||||||
|
$this->file = $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isValid(): bool {
|
||||||
|
return
|
||||||
|
$this->file >= 0 && $this->file < 8 &&
|
||||||
|
$this->rank >= 0 && $this->rank < 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString(): string {
|
||||||
|
return ["a", "b", "c", "d", "e", "f", "g", "h"][$this->file] . ($this->rank + 1);
|
||||||
|
}
|
||||||
|
}
|
37
tests/Game/FieldBitMapTest.php
Normal file
37
tests/Game/FieldBitMapTest.php
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Game\FieldBitMap;
|
||||||
|
use Game\Position;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
final class FieldBitMapTest extends TestCase {
|
||||||
|
|
||||||
|
public function testEmptyMapHasPositions() {
|
||||||
|
$subject = FieldBitMap::empty();
|
||||||
|
|
||||||
|
$this->assertTrue($subject->isEmpty());
|
||||||
|
$this->assertEmpty($subject->getPositions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFullMapHasAllPositions() {
|
||||||
|
$subject = FieldBitMap::full();
|
||||||
|
|
||||||
|
$this->assertFalse($subject->isEmpty());
|
||||||
|
$this->assertCount(64, $subject->getPositions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMapPositionsAreRetained() {
|
||||||
|
$positions = [
|
||||||
|
new Position(0, 0),
|
||||||
|
new Position(3, 4),
|
||||||
|
new Position(7, 7),
|
||||||
|
];
|
||||||
|
|
||||||
|
$subject = new FieldBitMap($positions);
|
||||||
|
|
||||||
|
$this->assertFalse($subject->isEmpty());
|
||||||
|
$this->assertEquals($positions, $subject->getPositions());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
44
tests/Game/PositionTest.php
Normal file
44
tests/Game/PositionTest.php
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Game\Position;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
final class PositionTest extends TestCase {
|
||||||
|
|
||||||
|
public function testIsValid_default_min() {
|
||||||
|
$subject = new Position(0, 0);
|
||||||
|
$this->assertTrue($subject->isValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsValid_default_max() {
|
||||||
|
$subject = new Position(7, 7);
|
||||||
|
$this->assertTrue($subject->isValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsValid_fileTooHigh() {
|
||||||
|
$subject = new Position(8, 7);
|
||||||
|
$this->assertFalse($subject->isValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsValid_RankTooHigh() {
|
||||||
|
$subject = new Position(7, 8);
|
||||||
|
$this->assertFalse($subject->isValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsValid_fileTooLow() {
|
||||||
|
$subject = new Position(-1, 0);
|
||||||
|
$this->assertFalse($subject->isValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsValid_RankTooLow() {
|
||||||
|
$subject = new Position(0, -1);
|
||||||
|
$this->assertFalse($subject->isValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testToString() {
|
||||||
|
$subject = new Position(4, 5);
|
||||||
|
|
||||||
|
$this->assertEquals("e6", strval($subject));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue