Completed
Push — master ( 144ff2...6ebbcb )
by Jesse
02:12
created

Player::number()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php declare(strict_types=1);
2
3
namespace Stratadox\CardGame\Match;
4
5
use function count;
6
use Stratadox\CardGame\DomainEventRecorder;
7
use Stratadox\CardGame\DomainEventRecording;
8
use Throwable;
9
10
final class Player implements DomainEventRecorder
11
{
12
    use DomainEventRecording;
13
14
    private $playerNumber;
15
    private $cards;
16
    private $maxHandSize;
17
    private $mana;
18
19
    public function __construct(
20
        int $id,
21
        Cards $cards,
22
        int $maxHandSize,
23
        Mana $mana
24
    ) {
25
        $this->playerNumber = $id;
26
        $this->cards = $cards;
27
        $this->maxHandSize = $maxHandSize;
28
        $this->mana = $mana;
29
    }
30
31
    public static function from(int $playerId, Cards $cards): self
32
    {
33
        return new self($playerId, $cards, 7, new Mana(4));
34
    }
35
36
    /** @throws NoSuchCard */
37
    public function cardInPlay(int $number): Card
38
    {
39
        try {
40
            return $this->cards->inPlay()[$number];
41
        } catch (Throwable $notFound) {
42
            throw NoSuchCard::atPosition($number, $notFound);
43
        }
44
    }
45
46
    /** @throws NotEnoughMana */
47
    public function playTheCard(int $cardNumber, MatchId $match): void
48
    {
49
        $card = $this->cards->inHand()[$cardNumber];
50
51
        if ($this->mana->isLessThan($card->cost())) {
52
            throw NotEnoughMana::toPlayThatCard();
53
        }
54
55
        $this->mana = $this->mana->minus($card->cost());
56
        $card->play($match, count($this->cards->inPlay()), $this->playerNumber);
57
58
        $this->happened(...$card->domainEvents());
59
        $card->eraseEvents();
60
    }
61
62
    /** @throws NoSuchCard */
63
    public function attackWith(int $cardNumber, MatchId $match): void
64
    {
65
        $card = $this->cardInPlay($cardNumber);
66
        $card->sendToAttack($match, count($this->attackers()), $this->playerNumber);
67
68
        $this->happened(...$card->domainEvents());
69
        $card->eraseEvents();
70
    }
71
72
    /** @throws NoSuchCard */
73
    public function defendAgainst(
74
        int $attacker,
75
        int $defender,
76
        MatchId $match
77
    ): void {
78
        $card = $this->cardInPlay($defender);
79
        $card->sendToDefendAgainst($match, $attacker, $this->playerNumber);
80
81
        $this->happened(...$card->domainEvents());
82
        $card->eraseEvents();
83
    }
84
85
    public function attackers(): Cards
86
    {
87
        return $this->cards->thatAttack();
88
    }
89
90
    public function drawOpeningHand(MatchId $match): void
91
    {
92
        for ($i = 0; $i < $this->maxHandSize; $i++) {
93
            $this->cards->drawFromTopOfDeck($match, $this->playerNumber);
94
        }
95
        foreach ($this->cards->inHand() as $card) {
96
            $this->happened(...$card->domainEvents());
97
            $card->eraseEvents();
98
        }
99
    }
100
101
    public function counterTheAttackersOf(
102
        int $attackingPlayer,
103
        MatchId $match,
104
        Cards $attackers
105
    ): void {
106
        foreach ($this->cards->thatDefend() as $defender) {
107
            $defender->counterAttack(
108
                $match,
109
                $attackers->theOneThatAttacksTheAmbushOf($defender),
110
                $this->playerNumber,
111
                $attackingPlayer
112
            );
113
            $this->happened(...$defender->domainEvents());
114
            $defender->eraseEvents();
115
        }
116
    }
117
}
118