1<?php ...
 2 
 3namespace Thunk\Verbs\Examples\Monopoly\Events\Gameplay;
 4 
 5use Thunk\Verbs\Attributes\Autodiscovery\AppliesToState;
 6use Thunk\Verbs\Event;
 7use Thunk\Verbs\Examples\Monopoly\Game\Phase;
 8use Thunk\Verbs\Examples\Monopoly\Game\Spaces\Property;
 9use Thunk\Verbs\Examples\Monopoly\States\GameState;
10use Thunk\Verbs\Examples\Monopoly\States\PlayerState; 
11 
12#[AppliesToState(GameState::class)]
13#[AppliesToState(PlayerState::class)]
14class PurchasedProperty extends Event
15{
16    use PlayerAction;
17 
18    public function __construct(
19        public int $game_id,
20        public int $player_id,
21        public Property $property,
22    ) {}
23 
24    public function validatePlayer(PlayerState $player)
25    {
26        $this->assert($player->location === $this->property, 'You must land on a property to buy it.');
27        $this->assert($player->money->isGreaterThanOrEqualTo($this->property->price()), "You do not have enough money to buy {$this->property->name()}.");
28    }
29 
30    public function validateGame(GameState $game)
31    {
32        $this->assert($game->bank->hasDeed($this->property), "{$this->property->name()} is not for sale.");
33        $this->assert($game->phase_complete, 'You must finish what you’re doing before purchasing a property.');
34        $this->assert($game->phase->canTransitionTo(Phase::Purchase), 'You are not allowed to purchase properties right now.');
35    }
36 
37    public function applyToGame(GameState $game)
38    {
39        $game->phase = Phase::Purchase;
40        $game->phase_complete = true;
41        $game->bank->purchaseDeed($this->property);
42    }
43 
44    public function applyToPlayer(PlayerState $player)
45    {
46        $player->deeds->push($this->property);
47        $player->money = $player->money->minus($this->property->price());
48        $this->property->setOwner($player);
49    }
50}