diff --git a/src/Domain/BasicStrategy.php b/src/Domain/BasicStrategy.php index 7d0f2e9..49335d3 100644 --- a/src/Domain/BasicStrategy.php +++ b/src/Domain/BasicStrategy.php @@ -9,6 +9,38 @@ public function decide(Hand $hand, Card $dealerCard): Decision $value = $hand->value(); $dealerValue = $dealerCard->numericValue(); + if ($hand->isPair()) { + $rank = $hand->pairRank(); + + if ($rank === 'Ace' || $rank === '8') { + return Decision::Split; + } + + if ($rank === '9' && !in_array($dealerValue, [7, 10, 11], true)) { + return Decision::Split; + } + + if ($rank === '7' && $dealerValue >= 2 && $dealerValue <= 7) { + return Decision::Split; + } + + if ($rank === '6' && $dealerValue >= 2 && $dealerValue <= 6) { + return Decision::Split; + } + + if ($rank === '4' && $dealerValue >= 5 && $dealerValue <= 6) { + return Decision::Split; + } + + if ($rank === '3' && $dealerValue >= 2 && $dealerValue <= 7) { + return Decision::Split; + } + + if ($rank === '2' && $dealerValue >= 2 && $dealerValue <= 7) { + return Decision::Split; + } + } + if ($hand->isSoft() && $value === 18) { if ($dealerValue >= 3 && $dealerValue <= 6) { return Decision::Double; diff --git a/src/Domain/Hand.php b/src/Domain/Hand.php index 2177526..05b0fc9 100644 --- a/src/Domain/Hand.php +++ b/src/Domain/Hand.php @@ -57,4 +57,15 @@ public function isSoft(): bool return $aces > 0 && $total <= 21; } + + public function isPair(): bool + { + return count($this->cards) === 2 + && $this->cards[0]->rank() === $this->cards[1]->rank(); + } + + public function pairRank(): string + { + return $this->cards[0]->rank(); + } } diff --git a/tests/Domain/BasicStrategyTest.php b/tests/Domain/BasicStrategyTest.php index eeaa732..c2802da 100644 --- a/tests/Domain/BasicStrategyTest.php +++ b/tests/Domain/BasicStrategyTest.php @@ -340,8 +340,8 @@ public function testHard8ShouldAlwaysHit(): void $strategy = new BasicStrategy(); $hand = new Hand(); - $hand->addCard(new Card('4', 'Hearts')); - $hand->addCard(new Card('4', 'Spades')); + $hand->addCard(new Card('5', 'Hearts')); + $hand->addCard(new Card('3', 'Spades')); $dealerCard = new Card('6', 'Diamonds'); @@ -386,4 +386,134 @@ public function testHard16AgainstDealer7ShouldHit(): void $this->assertSame(Decision::Hit, $strategy->decide($hand, $dealerCard)); } + + public function testPairOf8sShouldAlwaysSplit(): void + { + $strategy = new BasicStrategy(); + + $hand = new Hand(); + $hand->addCard(new Card('8', 'Hearts')); + $hand->addCard(new Card('8', 'Spades')); + + $dealerCard = new Card('6', 'Diamonds'); + + $this->assertSame(Decision::Split, $strategy->decide($hand, $dealerCard)); + } + + public function testPairOf9sAgainstDealer6ShouldSplit(): void + { + $strategy = new BasicStrategy(); + + $hand = new Hand(); + $hand->addCard(new Card('9', 'Hearts')); + $hand->addCard(new Card('9', 'Spades')); + + $dealerCard = new Card('6', 'Diamonds'); + + $this->assertSame(Decision::Split, $strategy->decide($hand, $dealerCard)); + } + + public function testPairOf9sAgainstDealer7ShouldStand(): void + { + $strategy = new BasicStrategy(); + + $hand = new Hand(); + $hand->addCard(new Card('9', 'Hearts')); + $hand->addCard(new Card('9', 'Spades')); + + $dealerCard = new Card('7', 'Diamonds'); + + $this->assertSame(Decision::Stand, $strategy->decide($hand, $dealerCard)); + } + + public function testPairOf7sAgainstDealer5ShouldSplit(): void + { + $strategy = new BasicStrategy(); + + $hand = new Hand(); + $hand->addCard(new Card('7', 'Hearts')); + $hand->addCard(new Card('7', 'Spades')); + + $dealerCard = new Card('5', 'Diamonds'); + + $this->assertSame(Decision::Split, $strategy->decide($hand, $dealerCard)); + } + + public function testPairOf6sAgainstDealer4ShouldSplit(): void + { + $strategy = new BasicStrategy(); + + $hand = new Hand(); + $hand->addCard(new Card('6', 'Hearts')); + $hand->addCard(new Card('6', 'Spades')); + + $dealerCard = new Card('4', 'Diamonds'); + + $this->assertSame(Decision::Split, $strategy->decide($hand, $dealerCard)); + } + + public function testPairOf4sAgainstDealer5ShouldSplit(): void + { + $strategy = new BasicStrategy(); + + $hand = new Hand(); + $hand->addCard(new Card('4', 'Hearts')); + $hand->addCard(new Card('4', 'Spades')); + + $dealerCard = new Card('5', 'Diamonds'); + + $this->assertSame(Decision::Split, $strategy->decide($hand, $dealerCard)); + } + + public function testPairOf3sAgainstDealer4ShouldSplit(): void + { + $strategy = new BasicStrategy(); + + $hand = new Hand(); + $hand->addCard(new Card('3', 'Hearts')); + $hand->addCard(new Card('3', 'Spades')); + + $dealerCard = new Card('4', 'Diamonds'); + + $this->assertSame(Decision::Split, $strategy->decide($hand, $dealerCard)); + } + + public function testPairOf2sAgainstDealer4ShouldSplit(): void + { + $strategy = new BasicStrategy(); + + $hand = new Hand(); + $hand->addCard(new Card('2', 'Hearts')); + $hand->addCard(new Card('2', 'Spades')); + + $dealerCard = new Card('4', 'Diamonds'); + + $this->assertSame(Decision::Split, $strategy->decide($hand, $dealerCard)); + } + + public function testPairOf5sShouldNotSplit(): void + { + $strategy = new BasicStrategy(); + + $hand = new Hand(); + $hand->addCard(new Card('5', 'Hearts')); + $hand->addCard(new Card('5', 'Spades')); + + $dealerCard = new Card('6', 'Diamonds'); + + $this->assertSame(Decision::Double, $strategy->decide($hand, $dealerCard)); + } + + public function testPairOf10sShouldNotSplit(): void + { + $strategy = new BasicStrategy(); + + $hand = new Hand(); + $hand->addCard(new Card('10', 'Hearts')); + $hand->addCard(new Card('10', 'Spades')); + + $dealerCard = new Card('6', 'Diamonds'); + + $this->assertSame(Decision::Stand, $strategy->decide($hand, $dealerCard)); + } } \ No newline at end of file diff --git a/tests/Domain/HandTest.php b/tests/Domain/HandTest.php index 146f465..4b0df49 100644 --- a/tests/Domain/HandTest.php +++ b/tests/Domain/HandTest.php @@ -70,4 +70,31 @@ public function testHandWithAceCountedAs11IsSoft(): void $this->assertTrue($hand->isSoft()); } + + public function testHandWithTwoIdenticalRanksIsPair(): void + { + $hand = new Hand(); + $hand->addCard(new Card('8', 'Hearts')); + $hand->addCard(new Card('8', 'Spades')); + + $this->assertTrue($hand->isPair()); + } + + public function testHandWithDifferentRanksIsNotPair(): void + { + $hand = new Hand(); + $hand->addCard(new Card('8', 'Hearts')); + $hand->addCard(new Card('9', 'Spades')); + + $this->assertFalse($hand->isPair()); + } + + public function testPairRankReturnsCardRank(): void + { + $hand = new Hand(); + $hand->addCard(new Card('8', 'Hearts')); + $hand->addCard(new Card('8', 'Spades')); + + $this->assertSame('8', $hand->pairRank()); + } }