From ae480a0eba421c3bca3e35cf8abb5d6e1b924d9a Mon Sep 17 00:00:00 2001 From: florentdevk Date: Mon, 22 Jun 2026 21:11:02 +0200 Subject: [PATCH 01/11] feat: add BasicStrategy and Decision enum with first rule --- src/Domain/BasicStrategy.php | 11 +++++++++++ src/Domain/Decision.php | 11 +++++++++++ tests/Domain/BasicStrategyTest.php | 25 +++++++++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 src/Domain/BasicStrategy.php create mode 100644 src/Domain/Decision.php create mode 100644 tests/Domain/BasicStrategyTest.php diff --git a/src/Domain/BasicStrategy.php b/src/Domain/BasicStrategy.php new file mode 100644 index 0000000..6a263b9 --- /dev/null +++ b/src/Domain/BasicStrategy.php @@ -0,0 +1,11 @@ +addCard(new Card('9', 'Hearts')); + $hand->addCard(new Card('7', 'Spades')); + + $dealerCard = new Card('10', 'Diamonds'); + + $this->assertSame(Decision::Hit, $strategy->decide($hand, $dealerCard)); + } +} \ No newline at end of file From 528a607d45e947b95c8d13fa0515b6318bde80e4 Mon Sep 17 00:00:00 2001 From: florentdevk Date: Mon, 22 Jun 2026 21:12:49 +0200 Subject: [PATCH 02/11] feat: BasicStrategy stands on hard 17 or more --- src/Domain/BasicStrategy.php | 6 ++++++ tests/Domain/BasicStrategyTest.php | 13 +++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/Domain/BasicStrategy.php b/src/Domain/BasicStrategy.php index 6a263b9..152f4bb 100644 --- a/src/Domain/BasicStrategy.php +++ b/src/Domain/BasicStrategy.php @@ -6,6 +6,12 @@ final class BasicStrategy { public function decide(Hand $hand, Card $dealerCard): Decision { + $value = $hand->value(); + + if ($value >= 17) { + return Decision::Stand; + } + return Decision::Hit; } } \ No newline at end of file diff --git a/tests/Domain/BasicStrategyTest.php b/tests/Domain/BasicStrategyTest.php index 8b862e5..aec276b 100644 --- a/tests/Domain/BasicStrategyTest.php +++ b/tests/Domain/BasicStrategyTest.php @@ -22,4 +22,17 @@ public function testHard16AgainstDealerTenShouldHit(): void $this->assertSame(Decision::Hit, $strategy->decide($hand, $dealerCard)); } + + public function testHard17ShouldStand(): void + { + $strategy = new BasicStrategy(); + + $hand = new Hand(); + $hand->addCard(new Card('King', 'Hearts')); + $hand->addCard(new Card('7', 'Spades')); + + $dealerCard = new Card('6', 'Diamonds'); + + $this->assertSame(Decision::Stand, $strategy->decide($hand, $dealerCard)); + } } \ No newline at end of file From 14025d2d4a5d4fedd2773cbf619cd2ae6f8b3a2f Mon Sep 17 00:00:00 2001 From: florentdevk Date: Mon, 22 Jun 2026 21:16:28 +0200 Subject: [PATCH 03/11] feat: BasicStrategy stands on hard 12-16 against dealer 4-6 --- src/Domain/BasicStrategy.php | 5 +++++ tests/Domain/BasicStrategyTest.php | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/Domain/BasicStrategy.php b/src/Domain/BasicStrategy.php index 152f4bb..b5106ec 100644 --- a/src/Domain/BasicStrategy.php +++ b/src/Domain/BasicStrategy.php @@ -7,11 +7,16 @@ final class BasicStrategy public function decide(Hand $hand, Card $dealerCard): Decision { $value = $hand->value(); + $dealerValue = $dealerCard->numericValue(); if ($value >= 17) { return Decision::Stand; } + if ($value >= 12 && $value <= 16 && $dealerValue >= 4 && $dealerValue <= 6) { + return Decision::Stand; + } + return Decision::Hit; } } \ No newline at end of file diff --git a/tests/Domain/BasicStrategyTest.php b/tests/Domain/BasicStrategyTest.php index aec276b..c1548cc 100644 --- a/tests/Domain/BasicStrategyTest.php +++ b/tests/Domain/BasicStrategyTest.php @@ -33,6 +33,18 @@ public function testHard17ShouldStand(): void $dealerCard = new Card('6', 'Diamonds'); + $this->assertSame(Decision::Stand, $strategy->decide($hand, $dealerCard)); + } + public function testHard12AgainstDealer4ShouldStand(): void + { + $strategy = new BasicStrategy(); + + $hand = new Hand(); + $hand->addCard(new Card('7', 'Hearts')); + $hand->addCard(new Card('5', 'Spades')); + + $dealerCard = new Card('4', 'Diamonds'); + $this->assertSame(Decision::Stand, $strategy->decide($hand, $dealerCard)); } } \ No newline at end of file From a2854acb58b159c68bd523964391f7c1de1b1726 Mon Sep 17 00:00:00 2001 From: florentdevk Date: Mon, 22 Jun 2026 21:20:16 +0200 Subject: [PATCH 04/11] feat: BasicStrategy stands on hard 13-16 against dealer 2-6 --- src/Domain/BasicStrategy.php | 6 +++++- tests/Domain/BasicStrategyTest.php | 13 +++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Domain/BasicStrategy.php b/src/Domain/BasicStrategy.php index b5106ec..96f6c2a 100644 --- a/src/Domain/BasicStrategy.php +++ b/src/Domain/BasicStrategy.php @@ -13,7 +13,11 @@ public function decide(Hand $hand, Card $dealerCard): Decision return Decision::Stand; } - if ($value >= 12 && $value <= 16 && $dealerValue >= 4 && $dealerValue <= 6) { + if ($value >= 13 && $value <= 16 && $dealerValue >= 2 && $dealerValue <= 6) { + return Decision::Stand; + } + + if ($value === 12 && $dealerValue >= 4 && $dealerValue <= 6) { return Decision::Stand; } diff --git a/tests/Domain/BasicStrategyTest.php b/tests/Domain/BasicStrategyTest.php index c1548cc..c69431c 100644 --- a/tests/Domain/BasicStrategyTest.php +++ b/tests/Domain/BasicStrategyTest.php @@ -47,4 +47,17 @@ public function testHard12AgainstDealer4ShouldStand(): void $this->assertSame(Decision::Stand, $strategy->decide($hand, $dealerCard)); } + + public function testHard13AgainstDealer2ShouldStand(): void + { + $strategy = new BasicStrategy(); + + $hand = new Hand(); + $hand->addCard(new Card('7', 'Hearts')); + $hand->addCard(new Card('6', 'Spades')); + + $dealerCard = new Card('2', 'Diamonds'); + + $this->assertSame(Decision::Stand, $strategy->decide($hand, $dealerCard)); + } } \ No newline at end of file From 428297375e1a8c52f3a271d75cde6d881292a57e Mon Sep 17 00:00:00 2001 From: florentdevk Date: Mon, 22 Jun 2026 21:22:48 +0200 Subject: [PATCH 05/11] feat: BasicStrategy doubles on hard 11 against dealer 2-10 --- src/Domain/BasicStrategy.php | 4 ++++ tests/Domain/BasicStrategyTest.php | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/Domain/BasicStrategy.php b/src/Domain/BasicStrategy.php index 96f6c2a..4cbf465 100644 --- a/src/Domain/BasicStrategy.php +++ b/src/Domain/BasicStrategy.php @@ -21,6 +21,10 @@ public function decide(Hand $hand, Card $dealerCard): Decision return Decision::Stand; } + if ($value === 11 && $dealerValue >= 2 && $dealerValue <= 10) { + return Decision::Double; + } + return Decision::Hit; } } \ No newline at end of file diff --git a/tests/Domain/BasicStrategyTest.php b/tests/Domain/BasicStrategyTest.php index c69431c..f364527 100644 --- a/tests/Domain/BasicStrategyTest.php +++ b/tests/Domain/BasicStrategyTest.php @@ -60,4 +60,17 @@ public function testHard13AgainstDealer2ShouldStand(): void $this->assertSame(Decision::Stand, $strategy->decide($hand, $dealerCard)); } + + public function testHard11AgainstDealer6ShouldDouble(): void + { + $strategy = new BasicStrategy(); + + $hand = new Hand(); + $hand->addCard(new Card('7', 'Hearts')); + $hand->addCard(new Card('4', 'Spades')); + + $dealerCard = new Card('6', 'Diamonds'); + + $this->assertSame(Decision::Double, $strategy->decide($hand, $dealerCard)); + } } \ No newline at end of file From e04b6be40f289e0c2234e2d25178dae30c6db407 Mon Sep 17 00:00:00 2001 From: florentdevk Date: Mon, 22 Jun 2026 21:28:43 +0200 Subject: [PATCH 06/11] feat: BasicStrategy doubles on hard 10 against dealer 2-9 --- src/Domain/BasicStrategy.php | 4 ++++ tests/Domain/BasicStrategyTest.php | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/Domain/BasicStrategy.php b/src/Domain/BasicStrategy.php index 4cbf465..8096b61 100644 --- a/src/Domain/BasicStrategy.php +++ b/src/Domain/BasicStrategy.php @@ -25,6 +25,10 @@ public function decide(Hand $hand, Card $dealerCard): Decision return Decision::Double; } + if ($value === 10 && $dealerValue >= 2 && $dealerValue <= 9) { + return Decision::Double; + } + return Decision::Hit; } } \ No newline at end of file diff --git a/tests/Domain/BasicStrategyTest.php b/tests/Domain/BasicStrategyTest.php index f364527..b6fc37a 100644 --- a/tests/Domain/BasicStrategyTest.php +++ b/tests/Domain/BasicStrategyTest.php @@ -73,4 +73,17 @@ public function testHard11AgainstDealer6ShouldDouble(): void $this->assertSame(Decision::Double, $strategy->decide($hand, $dealerCard)); } + + public function testHard10AgainstDealer5ShouldDouble(): void + { + $strategy = new BasicStrategy(); + + $hand = new Hand(); + $hand->addCard(new Card('6', 'Hearts')); + $hand->addCard(new Card('4', 'Spades')); + + $dealerCard = new Card('5', 'Diamonds'); + + $this->assertSame(Decision::Double, $strategy->decide($hand, $dealerCard)); + } } \ No newline at end of file From cb136f48aacdde0db8aa8fa91b161abf84b6ee25 Mon Sep 17 00:00:00 2001 From: florentdevk Date: Mon, 22 Jun 2026 21:30:07 +0200 Subject: [PATCH 07/11] feat: BasicStrategy doubles on hard 9 against dealer 3-6 --- src/Domain/BasicStrategy.php | 4 ++++ tests/Domain/BasicStrategyTest.php | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/Domain/BasicStrategy.php b/src/Domain/BasicStrategy.php index 8096b61..872c398 100644 --- a/src/Domain/BasicStrategy.php +++ b/src/Domain/BasicStrategy.php @@ -29,6 +29,10 @@ public function decide(Hand $hand, Card $dealerCard): Decision return Decision::Double; } + if ($value === 9 && $dealerValue >= 3 && $dealerValue <= 6) { + return Decision::Double; + } + return Decision::Hit; } } \ No newline at end of file diff --git a/tests/Domain/BasicStrategyTest.php b/tests/Domain/BasicStrategyTest.php index b6fc37a..907706a 100644 --- a/tests/Domain/BasicStrategyTest.php +++ b/tests/Domain/BasicStrategyTest.php @@ -86,4 +86,17 @@ public function testHard10AgainstDealer5ShouldDouble(): void $this->assertSame(Decision::Double, $strategy->decide($hand, $dealerCard)); } + + public function testHard9AgainstDealer3ShouldDouble(): void + { + $strategy = new BasicStrategy(); + + $hand = new Hand(); + $hand->addCard(new Card('5', 'Hearts')); + $hand->addCard(new Card('4', 'Spades')); + + $dealerCard = new Card('3', 'Diamonds'); + + $this->assertSame(Decision::Double, $strategy->decide($hand, $dealerCard)); + } } \ No newline at end of file From 05c7889fd6513e9200f6ed6e8ab186fc4f4e7b1b Mon Sep 17 00:00:00 2001 From: florentdevk Date: Mon, 22 Jun 2026 21:33:26 +0200 Subject: [PATCH 08/11] feat: BasicStrategy doubles on soft 18 against dealer 3-6 --- src/Domain/BasicStrategy.php | 4 ++++ tests/Domain/BasicStrategyTest.php | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/Domain/BasicStrategy.php b/src/Domain/BasicStrategy.php index 872c398..2a1f201 100644 --- a/src/Domain/BasicStrategy.php +++ b/src/Domain/BasicStrategy.php @@ -9,6 +9,10 @@ public function decide(Hand $hand, Card $dealerCard): Decision $value = $hand->value(); $dealerValue = $dealerCard->numericValue(); + if ($hand->isSoft() && $value === 18 && $dealerValue >= 3 && $dealerValue <= 6) { + return Decision::Double; + } + if ($value >= 17) { return Decision::Stand; } diff --git a/tests/Domain/BasicStrategyTest.php b/tests/Domain/BasicStrategyTest.php index 907706a..1e86628 100644 --- a/tests/Domain/BasicStrategyTest.php +++ b/tests/Domain/BasicStrategyTest.php @@ -99,4 +99,17 @@ public function testHard9AgainstDealer3ShouldDouble(): void $this->assertSame(Decision::Double, $strategy->decide($hand, $dealerCard)); } + + public function testSoft18AgainstDealer5ShouldDouble(): void + { + $strategy = new BasicStrategy(); + + $hand = new Hand(); + $hand->addCard(new Card('Ace', 'Hearts')); + $hand->addCard(new Card('7', 'Spades')); + + $dealerCard = new Card('5', 'Diamonds'); + + $this->assertSame(Decision::Double, $strategy->decide($hand, $dealerCard)); + } } \ No newline at end of file From 69c6a21502d5e54b2ae68e08245572618bd24f9e Mon Sep 17 00:00:00 2001 From: florentdevk Date: Mon, 22 Jun 2026 21:34:44 +0200 Subject: [PATCH 09/11] test: soft 18 against dealer 2 should stand --- tests/Domain/BasicStrategyTest.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/Domain/BasicStrategyTest.php b/tests/Domain/BasicStrategyTest.php index 1e86628..9621b13 100644 --- a/tests/Domain/BasicStrategyTest.php +++ b/tests/Domain/BasicStrategyTest.php @@ -112,4 +112,17 @@ public function testSoft18AgainstDealer5ShouldDouble(): void $this->assertSame(Decision::Double, $strategy->decide($hand, $dealerCard)); } + + public function testSoft18AgainstDealer2ShouldStand(): void + { + $strategy = new BasicStrategy(); + + $hand = new Hand(); + $hand->addCard(new Card('Ace', 'Hearts')); + $hand->addCard(new Card('7', 'Spades')); + + $dealerCard = new Card('2', 'Diamonds'); + + $this->assertSame(Decision::Stand, $strategy->decide($hand, $dealerCard)); + } } \ No newline at end of file From f404d6269834e9b40a1789da25c487bd8f2454d3 Mon Sep 17 00:00:00 2001 From: florentdevk Date: Mon, 22 Jun 2026 21:36:43 +0200 Subject: [PATCH 10/11] feat: BasicStrategy doubles on soft 17 against dealer 3-6 --- src/Domain/BasicStrategy.php | 4 ++++ tests/Domain/BasicStrategyTest.php | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/Domain/BasicStrategy.php b/src/Domain/BasicStrategy.php index 2a1f201..6f6658e 100644 --- a/src/Domain/BasicStrategy.php +++ b/src/Domain/BasicStrategy.php @@ -13,6 +13,10 @@ public function decide(Hand $hand, Card $dealerCard): Decision return Decision::Double; } + if ($hand->isSoft() && $value === 17 && $dealerValue >= 3 && $dealerValue <= 6) { + return Decision::Double; + } + if ($value >= 17) { return Decision::Stand; } diff --git a/tests/Domain/BasicStrategyTest.php b/tests/Domain/BasicStrategyTest.php index 9621b13..691eaa2 100644 --- a/tests/Domain/BasicStrategyTest.php +++ b/tests/Domain/BasicStrategyTest.php @@ -125,4 +125,17 @@ public function testSoft18AgainstDealer2ShouldStand(): void $this->assertSame(Decision::Stand, $strategy->decide($hand, $dealerCard)); } + + public function testSoft17AgainstDealer4ShouldDouble(): void + { + $strategy = new BasicStrategy(); + + $hand = new Hand(); + $hand->addCard(new Card('Ace', 'Hearts')); + $hand->addCard(new Card('6', 'Spades')); + + $dealerCard = new Card('4', 'Diamonds'); + + $this->assertSame(Decision::Double, $strategy->decide($hand, $dealerCard)); + } } \ No newline at end of file From 34bf66f6448ea4e60876317e2a9557ef26ccf1e6 Mon Sep 17 00:00:00 2001 From: florentdevk Date: Mon, 22 Jun 2026 21:37:20 +0200 Subject: [PATCH 11/11] test: soft 19 or more should always stand --- tests/Domain/BasicStrategyTest.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/Domain/BasicStrategyTest.php b/tests/Domain/BasicStrategyTest.php index 691eaa2..d908571 100644 --- a/tests/Domain/BasicStrategyTest.php +++ b/tests/Domain/BasicStrategyTest.php @@ -138,4 +138,17 @@ public function testSoft17AgainstDealer4ShouldDouble(): void $this->assertSame(Decision::Double, $strategy->decide($hand, $dealerCard)); } + + public function testSoft19ShouldAlwaysStand(): void + { + $strategy = new BasicStrategy(); + + $hand = new Hand(); + $hand->addCard(new Card('Ace', 'Hearts')); + $hand->addCard(new Card('8', 'Spades')); + + $dealerCard = new Card('6', 'Diamonds'); + + $this->assertSame(Decision::Stand, $strategy->decide($hand, $dealerCard)); + } } \ No newline at end of file