Issues (11)

puzzles/Maze/MazePuzzle.php (1 issue)

1
<?php declare(strict_types=1);
2
3
namespace Stratadox\PuzzleSolver\Puzzle\Maze;
4
5
use Stratadox\PuzzleSolver\Move;
6
use Stratadox\PuzzleSolver\Puzzle;
7
use Stratadox\PuzzleSolver\Moves;
8
use function assert;
9
use function explode;
10
use function implode;
11
use const PHP_EOL;
12
13
final class MazePuzzle implements Puzzle
14
{
15
    /** @var Maze */
16
    private $maze;
17
    /** @var Hero */
18
    private $hero;
19
    /** @var Moves */
20
    private $actionsSoFar;
21
22
    public function __construct(Maze $maze, Hero $hero, Moves $actionsSoFar)
23
    {
24
        $this->maze = $maze;
25
        $this->hero = $hero;
26
        $this->actionsSoFar = $actionsSoFar;
27
    }
28
29
    public static function withHeroAndMaze(Hero $hero, Maze $maze): Puzzle
30
    {
31
        return new self($maze, $hero, Moves::none());
32
    }
33
34
    public function isSolved(): bool
35
    {
36
        return $this->maze->isCompletedBy($this->hero);
37
    }
38
39
    public function movesSoFar(): Moves
40
    {
41
        return $this->actionsSoFar;
42
    }
43
44
    public function representation(): string
45
    {
46
        $maze = explode(PHP_EOL, (string) $this->maze);
47
        $maze[$this->hero->y()][$this->hero->x()] = 'H';
48
        return implode(PHP_EOL, $maze);
49
    }
50
51
    public function possibleMoves(): Moves
52
    {
53
        return Action::all()->filterWith(function (Action $action) {
0 ignored issues
show
Bug Best Practice introduced by
The expression return Stratadox\PuzzleS...ion(...) { /* ... */ }) returns the type Stratadox\Collection\Collection which includes types incompatible with the type-hinted return Stratadox\PuzzleSolver\Moves.
Loading history...
54
            return $this->maze->isValidPosition($this->hero->after($action));
55
        });
56
    }
57
58
    public function afterMaking(Move ...$moves): Puzzle
59
    {
60
        $new = clone $this;
61
        foreach ($moves as $move) {
62
            assert($move instanceof Action);
63
            $new->hero = $new->hero->after($move);
64
            $new->actionsSoFar = $new->actionsSoFar->add($move);
65
        }
66
        return $new;
67
    }
68
69
    public function hero(): Hero
70
    {
71
        return $this->hero;
72
    }
73
}
74