@arcanahq/cardgames 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +722 -0
- package/as-test.config.js +36 -0
- package/asconfig.json +22 -0
- package/assembly/__tests__/blackjack/actions/common.spec.ts +180 -0
- package/assembly/__tests__/blackjack/actions/dealer_scenarios.spec.ts +452 -0
- package/assembly/__tests__/blackjack/actions/double.spec.ts +128 -0
- package/assembly/__tests__/blackjack/actions/edge_cases.spec.ts +1041 -0
- package/assembly/__tests__/blackjack/actions/insurance.spec.ts +39 -0
- package/assembly/__tests__/blackjack/actions/split.spec.ts +96 -0
- package/assembly/__tests__/blackjack/actions/stand.spec.ts +103 -0
- package/assembly/__tests__/blackjack/actions/surrender.spec.ts +89 -0
- package/assembly/__tests__/blackjack/actions/test.ts +18 -0
- package/assembly/__tests__/blackjack/rules.spec.ts +231 -0
- package/assembly/__tests__/deck/deck.spec.ts +551 -0
- package/assembly/__tests__/deck/shoe.spec.ts +410 -0
- package/assembly/__tests__/poker/betting_round.spec.ts +103 -0
- package/assembly/__tests__/poker/omaha.spec.ts +171 -0
- package/assembly/__tests__/poker/pots.spec.ts +255 -0
- package/assembly/__tests__/poker/showdown.spec.ts +324 -0
- package/assembly/__tests__/poker/six_plus.spec.ts +152 -0
- package/assembly/__tests__/poker/stakes.spec.ts +384 -0
- package/assembly/__tests__/poker/stud.spec.ts +190 -0
- package/assembly/__tests__/poker/test.ts +13 -0
- package/assembly/__tests__/test.ts +11 -0
- package/assembly/blackjack/actions.ts +191 -0
- package/assembly/blackjack/blackjack.ts +571 -0
- package/assembly/blackjack/rules.ts +11 -0
- package/assembly/cardgames.ts +314 -0
- package/assembly/cards.ts +314 -0
- package/assembly/cashgames/cash_game_types.ts +142 -0
- package/assembly/cashgames/cash_game_utils.ts +223 -0
- package/assembly/cashgames/index.ts +10 -0
- package/assembly/deck/deck.ts +744 -0
- package/assembly/deck/index.ts +9 -0
- package/assembly/index.ts +28 -0
- package/assembly/poker/index.ts +17 -0
- package/assembly/poker/omaha_evaluator.ts +121 -0
- package/assembly/poker/poker_game_types.ts +233 -0
- package/assembly/poker/poker_game_utils.ts +671 -0
- package/assembly/poker/showdown.ts +106 -0
- package/assembly/poker/showdown_evaluator.ts +225 -0
- package/assembly/poker/six_plus_showdown.ts +96 -0
- package/assembly/poker/stud_evaluator.ts +60 -0
- package/assembly/poker/variant_utils.ts +51 -0
- package/assembly/poker/variants.ts +182 -0
- package/assembly/poker.ts +307 -0
- package/package.json +51 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Tests for insurance offer validation
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, test, expect } from "assemblyscript-unittest-framework/assembly";
|
|
7
|
+
import {
|
|
8
|
+
shouldOfferInsurance
|
|
9
|
+
} from "../../../blackjack/actions";
|
|
10
|
+
import { BlackjackRules } from "../../../blackjack/rules";
|
|
11
|
+
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// shouldOfferInsurance Tests
|
|
14
|
+
// ============================================================================
|
|
15
|
+
|
|
16
|
+
describe("shouldOfferInsurance", () => {
|
|
17
|
+
test("should offer insurance when dealer shows ace and insurance is enabled", () => {
|
|
18
|
+
const standardRules = BlackjackRules.standard();
|
|
19
|
+
expect(shouldOfferInsurance("A", standardRules)).equal(true);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test("should not offer insurance when dealer does not show ace", () => {
|
|
23
|
+
const standardRules = BlackjackRules.standard();
|
|
24
|
+
expect(shouldOfferInsurance("K", standardRules)).equal(false);
|
|
25
|
+
expect(shouldOfferInsurance("10", standardRules)).equal(false);
|
|
26
|
+
expect(shouldOfferInsurance("5", standardRules)).equal(false);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("should not offer insurance when insurance is disabled", () => {
|
|
30
|
+
const rules = new BlackjackRules(17, false, 4, false, true, false, false); // insuranceOffered = false
|
|
31
|
+
expect(shouldOfferInsurance("A", rules)).equal(false);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("should not offer insurance when dealer shows ace but insurance disabled", () => {
|
|
35
|
+
const rules = new BlackjackRules(17, false, 4, false, true, false, false); // insuranceOffered = false
|
|
36
|
+
expect(shouldOfferInsurance("A", rules)).equal(false);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Tests for split action validation and availability
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, test, expect } from "assemblyscript-unittest-framework/assembly";
|
|
7
|
+
import {
|
|
8
|
+
calculateAvailableActions,
|
|
9
|
+
validateCanSplit
|
|
10
|
+
} from "../../../blackjack/actions";
|
|
11
|
+
import { BlackjackRules } from "../../../blackjack/rules";
|
|
12
|
+
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// calculateAvailableActions - Split Tests
|
|
15
|
+
// ============================================================================
|
|
16
|
+
|
|
17
|
+
describe("calculateAvailableActions - Split", () => {
|
|
18
|
+
test("should allow split when cards can be split and under max hands", () => {
|
|
19
|
+
const standardRules = BlackjackRules.standard();
|
|
20
|
+
const actions = calculateAvailableActions(
|
|
21
|
+
2,
|
|
22
|
+
false,
|
|
23
|
+
false,
|
|
24
|
+
false,
|
|
25
|
+
false,
|
|
26
|
+
"PLAYING",
|
|
27
|
+
1, // playerHandsCount
|
|
28
|
+
true, // canSplit
|
|
29
|
+
standardRules
|
|
30
|
+
);
|
|
31
|
+
expect(actions.canSplit).equal(true);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("should not allow split when at max hands", () => {
|
|
35
|
+
const standardRules = BlackjackRules.standard();
|
|
36
|
+
const actions = calculateAvailableActions(
|
|
37
|
+
2,
|
|
38
|
+
false,
|
|
39
|
+
false,
|
|
40
|
+
false,
|
|
41
|
+
false,
|
|
42
|
+
"PLAYING",
|
|
43
|
+
4, // playerHandsCount (at max)
|
|
44
|
+
true,
|
|
45
|
+
standardRules
|
|
46
|
+
);
|
|
47
|
+
expect(actions.canSplit).equal(false);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("should not allow split when cards cannot be split", () => {
|
|
51
|
+
const standardRules = BlackjackRules.standard();
|
|
52
|
+
const actions = calculateAvailableActions(
|
|
53
|
+
2,
|
|
54
|
+
false,
|
|
55
|
+
false,
|
|
56
|
+
false,
|
|
57
|
+
false,
|
|
58
|
+
"PLAYING",
|
|
59
|
+
1,
|
|
60
|
+
false, // canSplit
|
|
61
|
+
standardRules
|
|
62
|
+
);
|
|
63
|
+
expect(actions.canSplit).equal(false);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// ============================================================================
|
|
68
|
+
// validateCanSplit Tests
|
|
69
|
+
// ============================================================================
|
|
70
|
+
|
|
71
|
+
describe("validateCanSplit", () => {
|
|
72
|
+
test("should not throw when hand can be split", () => {
|
|
73
|
+
const standardRules = BlackjackRules.standard();
|
|
74
|
+
validateCanSplit(2, 1, true, standardRules);
|
|
75
|
+
// If we get here, no error was thrown
|
|
76
|
+
expect(true).equal(true);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Note: AssemblyScript doesn't support try-catch, so we test that
|
|
80
|
+
// the function aborts on invalid input by checking the contract behavior
|
|
81
|
+
// In a real scenario, invalid split would cause the contract to abort
|
|
82
|
+
test("should validate split conditions correctly", () => {
|
|
83
|
+
const standardRules = BlackjackRules.standard();
|
|
84
|
+
// Valid conditions - should not abort
|
|
85
|
+
validateCanSplit(2, 1, true, standardRules);
|
|
86
|
+
expect(true).equal(true);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("should allow split when under max hands", () => {
|
|
90
|
+
const standardRules = BlackjackRules.standard();
|
|
91
|
+
validateCanSplit(2, 3, true, standardRules); // playerHandsCount = 3 (under max)
|
|
92
|
+
// If we get here, no error was thrown
|
|
93
|
+
expect(true).equal(true);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Tests for stand action validation and availability
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, test, expect } from "assemblyscript-unittest-framework/assembly";
|
|
7
|
+
import {
|
|
8
|
+
calculateAvailableActions,
|
|
9
|
+
validateCanStand
|
|
10
|
+
} from "../../../blackjack/actions";
|
|
11
|
+
import { BlackjackRules } from "../../../blackjack/rules";
|
|
12
|
+
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// calculateAvailableActions - Stand Tests
|
|
15
|
+
// ============================================================================
|
|
16
|
+
|
|
17
|
+
describe("calculateAvailableActions - Stand", () => {
|
|
18
|
+
test("should allow stand when in playing phase with active hand", () => {
|
|
19
|
+
const standardRules = BlackjackRules.standard();
|
|
20
|
+
const actions = calculateAvailableActions(
|
|
21
|
+
2, // handCardsLength
|
|
22
|
+
false, // handIsFromSplit
|
|
23
|
+
false, // handIsSplitAces
|
|
24
|
+
false, // handIsStanding
|
|
25
|
+
false, // handIsBusted
|
|
26
|
+
"PLAYING", // gamePhase
|
|
27
|
+
1, // playerHandsCount
|
|
28
|
+
false, // canSplit
|
|
29
|
+
standardRules
|
|
30
|
+
);
|
|
31
|
+
expect(actions.canStand).equal(true);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("should not allow stand when hand is already standing", () => {
|
|
35
|
+
const standardRules = BlackjackRules.standard();
|
|
36
|
+
const actions = calculateAvailableActions(
|
|
37
|
+
2,
|
|
38
|
+
false,
|
|
39
|
+
false,
|
|
40
|
+
true, // handIsStanding
|
|
41
|
+
false,
|
|
42
|
+
"PLAYING",
|
|
43
|
+
1,
|
|
44
|
+
false,
|
|
45
|
+
standardRules
|
|
46
|
+
);
|
|
47
|
+
expect(actions.canStand).equal(false);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("should not allow stand when hand is busted", () => {
|
|
51
|
+
const standardRules = BlackjackRules.standard();
|
|
52
|
+
const actions = calculateAvailableActions(
|
|
53
|
+
3,
|
|
54
|
+
false,
|
|
55
|
+
false,
|
|
56
|
+
false,
|
|
57
|
+
true, // handIsBusted
|
|
58
|
+
"PLAYING",
|
|
59
|
+
1,
|
|
60
|
+
false,
|
|
61
|
+
standardRules
|
|
62
|
+
);
|
|
63
|
+
expect(actions.canStand).equal(false);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test("should not allow stand when not in playing phase", () => {
|
|
67
|
+
const standardRules = BlackjackRules.standard();
|
|
68
|
+
const actions = calculateAvailableActions(
|
|
69
|
+
2,
|
|
70
|
+
false,
|
|
71
|
+
false,
|
|
72
|
+
false,
|
|
73
|
+
false,
|
|
74
|
+
"BETTING", // gamePhase
|
|
75
|
+
1,
|
|
76
|
+
false,
|
|
77
|
+
standardRules
|
|
78
|
+
);
|
|
79
|
+
expect(actions.canStand).equal(false);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// ============================================================================
|
|
84
|
+
// validateCanStand Tests
|
|
85
|
+
// ============================================================================
|
|
86
|
+
|
|
87
|
+
describe("validateCanStand", () => {
|
|
88
|
+
test("should not throw when hand can be stood", () => {
|
|
89
|
+
validateCanStand(false, false);
|
|
90
|
+
// If we get here, no error was thrown
|
|
91
|
+
expect(true).equal(true);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Note: AssemblyScript doesn't support try-catch, so we test that
|
|
95
|
+
// the function aborts on invalid input by checking the contract behavior
|
|
96
|
+
// In a real scenario, invalid stand would cause the contract to abort
|
|
97
|
+
test("should validate stand conditions correctly", () => {
|
|
98
|
+
// Valid conditions - should not abort
|
|
99
|
+
validateCanStand(false, false);
|
|
100
|
+
expect(true).equal(true);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Tests for surrender action validation and availability
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, test, expect } from "assemblyscript-unittest-framework/assembly";
|
|
7
|
+
import {
|
|
8
|
+
calculateAvailableActions,
|
|
9
|
+
validateCanSurrender
|
|
10
|
+
} from "../../../blackjack/actions";
|
|
11
|
+
import { BlackjackRules } from "../../../blackjack/rules";
|
|
12
|
+
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// calculateAvailableActions - Surrender Tests
|
|
15
|
+
// ============================================================================
|
|
16
|
+
|
|
17
|
+
describe("calculateAvailableActions - Surrender", () => {
|
|
18
|
+
test("should allow surrender on first two cards of original hand", () => {
|
|
19
|
+
const standardRules = BlackjackRules.standard();
|
|
20
|
+
const actions = calculateAvailableActions(
|
|
21
|
+
2,
|
|
22
|
+
false, // handIsFromSplit
|
|
23
|
+
false,
|
|
24
|
+
false,
|
|
25
|
+
false,
|
|
26
|
+
"PLAYING",
|
|
27
|
+
1,
|
|
28
|
+
false,
|
|
29
|
+
standardRules
|
|
30
|
+
);
|
|
31
|
+
expect(actions.canSurrender).equal(true);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("should not allow surrender on split hand", () => {
|
|
35
|
+
const standardRules = BlackjackRules.standard();
|
|
36
|
+
const actions = calculateAvailableActions(
|
|
37
|
+
2,
|
|
38
|
+
true, // handIsFromSplit
|
|
39
|
+
false,
|
|
40
|
+
false,
|
|
41
|
+
false,
|
|
42
|
+
"PLAYING",
|
|
43
|
+
2,
|
|
44
|
+
false,
|
|
45
|
+
standardRules
|
|
46
|
+
);
|
|
47
|
+
expect(actions.canSurrender).equal(false);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("should not allow surrender when surrender not allowed", () => {
|
|
51
|
+
const rules = new BlackjackRules(17, false, 4, false, false); // surrenderAllowed = false
|
|
52
|
+
const actions = calculateAvailableActions(
|
|
53
|
+
2,
|
|
54
|
+
false,
|
|
55
|
+
false,
|
|
56
|
+
false,
|
|
57
|
+
false,
|
|
58
|
+
"PLAYING",
|
|
59
|
+
1,
|
|
60
|
+
false,
|
|
61
|
+
rules
|
|
62
|
+
);
|
|
63
|
+
expect(actions.canSurrender).equal(false);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// ============================================================================
|
|
68
|
+
// validateCanSurrender Tests
|
|
69
|
+
// ============================================================================
|
|
70
|
+
|
|
71
|
+
describe("validateCanSurrender", () => {
|
|
72
|
+
test("should not throw when hand can be surrendered", () => {
|
|
73
|
+
const standardRules = BlackjackRules.standard();
|
|
74
|
+
validateCanSurrender(2, false, standardRules);
|
|
75
|
+
// If we get here, no error was thrown
|
|
76
|
+
expect(true).equal(true);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Note: AssemblyScript doesn't support try-catch, so we test that
|
|
80
|
+
// the function aborts on invalid input by checking the contract behavior
|
|
81
|
+
// In a real scenario, invalid surrender would cause the contract to abort
|
|
82
|
+
test("should validate surrender conditions correctly", () => {
|
|
83
|
+
const standardRules = BlackjackRules.standard();
|
|
84
|
+
// Valid conditions - should not abort
|
|
85
|
+
validateCanSurrender(2, false, standardRules);
|
|
86
|
+
expect(true).equal(true);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Test entry point for blackjack actions
|
|
4
|
+
* Imports all action test files
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Import common tests
|
|
8
|
+
import "./common.spec";
|
|
9
|
+
|
|
10
|
+
// Import action-specific tests
|
|
11
|
+
import "./stand.spec";
|
|
12
|
+
import "./double.spec";
|
|
13
|
+
import "./split.spec";
|
|
14
|
+
import "./surrender.spec";
|
|
15
|
+
import "./insurance.spec";
|
|
16
|
+
import "./dealer_scenarios.spec";
|
|
17
|
+
import "./edge_cases.spec";
|
|
18
|
+
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Comprehensive tests for blackjack rules configuration
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, test, expect } from "assemblyscript-unittest-framework/assembly";
|
|
7
|
+
import { BlackjackRules } from "../../blackjack/rules";
|
|
8
|
+
import { dealerShouldHit, isSoftHand, calculateBlackjackHandValue } from "../../blackjack/blackjack";
|
|
9
|
+
import { Card } from "../../cards";
|
|
10
|
+
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// BlackjackRules Class Tests
|
|
13
|
+
// ============================================================================
|
|
14
|
+
|
|
15
|
+
describe("BlackjackRules", () => {
|
|
16
|
+
test("should create standard rules with correct defaults", () => {
|
|
17
|
+
const rules = BlackjackRules.standard();
|
|
18
|
+
expect(rules.dealerStandValue).equal(17);
|
|
19
|
+
expect(rules.hitOnSoft17).equal(false);
|
|
20
|
+
expect(rules.maxSplitHands).equal(4);
|
|
21
|
+
expect(rules.doubleAfterSplit).equal(false);
|
|
22
|
+
expect(rules.surrenderAllowed).equal(true);
|
|
23
|
+
expect(rules.insuranceOffered).equal(true);
|
|
24
|
+
expect(rules.isSpanish21).equal(false);
|
|
25
|
+
expect(rules.deckSize).equal(52);
|
|
26
|
+
expect(rules.blackjackValue).equal(21);
|
|
27
|
+
expect(rules.bustValue).equal(22);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("should create Spanish 21 rules correctly", () => {
|
|
31
|
+
const rules = BlackjackRules.spanish21();
|
|
32
|
+
expect(rules.dealerStandValue).equal(17);
|
|
33
|
+
expect(rules.hitOnSoft17).equal(true);
|
|
34
|
+
expect(rules.maxSplitHands).equal(4);
|
|
35
|
+
expect(rules.doubleAfterSplit).equal(true);
|
|
36
|
+
expect(rules.surrenderAllowed).equal(true);
|
|
37
|
+
expect(rules.insuranceOffered).equal(false);
|
|
38
|
+
expect(rules.isSpanish21).equal(true);
|
|
39
|
+
expect(rules.deckSize).equal(48);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test("should create rules with dealer hitting on soft 17", () => {
|
|
43
|
+
const rules = BlackjackRules.dealerHitsSoft17();
|
|
44
|
+
expect(rules.dealerStandValue).equal(17);
|
|
45
|
+
expect(rules.hitOnSoft17).equal(true);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("should create rules allowing double after split", () => {
|
|
49
|
+
const rules = BlackjackRules.allowDoubleAfterSplit();
|
|
50
|
+
expect(rules.doubleAfterSplit).equal(true);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("should allow custom rule configuration", () => {
|
|
54
|
+
const rules = new BlackjackRules(
|
|
55
|
+
18, // dealerStandValue
|
|
56
|
+
true, // hitOnSoft17
|
|
57
|
+
3, // maxSplitHands
|
|
58
|
+
true, // doubleAfterSplit
|
|
59
|
+
false, // surrenderAllowed
|
|
60
|
+
false, // lateSurrender
|
|
61
|
+
false, // insuranceOffered
|
|
62
|
+
false // isSpanish21
|
|
63
|
+
);
|
|
64
|
+
expect(rules.dealerStandValue).equal(18);
|
|
65
|
+
expect(rules.hitOnSoft17).equal(true);
|
|
66
|
+
expect(rules.maxSplitHands).equal(3);
|
|
67
|
+
expect(rules.doubleAfterSplit).equal(true);
|
|
68
|
+
expect(rules.surrenderAllowed).equal(false);
|
|
69
|
+
expect(rules.insuranceOffered).equal(false);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("should set deck size to 48 for Spanish 21", () => {
|
|
73
|
+
const rules = new BlackjackRules(17, false, 4, false, true, false, true, true);
|
|
74
|
+
expect(rules.isSpanish21).equal(true);
|
|
75
|
+
expect(rules.deckSize).equal(48);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test("should set deck size to 52 for standard blackjack", () => {
|
|
79
|
+
const rules = new BlackjackRules(17, false, 4, false, true, false, true, false);
|
|
80
|
+
expect(rules.isSpanish21).equal(false);
|
|
81
|
+
expect(rules.deckSize).equal(52);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("should have correct payout defaults", () => {
|
|
85
|
+
const rules = BlackjackRules.standard();
|
|
86
|
+
expect(rules.payoutBlackjack).equal(1.5);
|
|
87
|
+
expect(rules.payoutWin).equal(1.0);
|
|
88
|
+
expect(rules.payoutPush).equal(1.0);
|
|
89
|
+
expect(rules.payoutLose).equal(0.0);
|
|
90
|
+
expect(rules.payoutSurrender).equal(0.5);
|
|
91
|
+
expect(rules.payoutInsurance).equal(2.0);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test("should allow custom payouts", () => {
|
|
95
|
+
const rules = new BlackjackRules(
|
|
96
|
+
17, false, 4, false, true, false, true, false,
|
|
97
|
+
2.0, // payoutBlackjack (6:5 instead of 3:2)
|
|
98
|
+
1.0, // payoutWin
|
|
99
|
+
1.0, // payoutPush
|
|
100
|
+
0.0, // payoutLose
|
|
101
|
+
0.5, // payoutSurrender
|
|
102
|
+
2.0 // payoutInsurance
|
|
103
|
+
);
|
|
104
|
+
expect(rules.payoutBlackjack).equal(2.0);
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// ============================================================================
|
|
109
|
+
// dealerShouldHit Tests (from core)
|
|
110
|
+
// ============================================================================
|
|
111
|
+
|
|
112
|
+
describe("dealerShouldHit (from core)", () => {
|
|
113
|
+
test("should hit when below stand value", () => {
|
|
114
|
+
const cards: Card[] = [];
|
|
115
|
+
cards.push(new Card("Hearts", "5"));
|
|
116
|
+
cards.push(new Card("Diamonds", "6"));
|
|
117
|
+
const rules = BlackjackRules.standard();
|
|
118
|
+
expect(dealerShouldHit(cards, rules)).equal(true);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test("should not hit when at or above stand value", () => {
|
|
122
|
+
const cards: Card[] = [];
|
|
123
|
+
cards.push(new Card("Hearts", "10"));
|
|
124
|
+
cards.push(new Card("Diamonds", "7"));
|
|
125
|
+
const rules = BlackjackRules.standard();
|
|
126
|
+
expect(dealerShouldHit(cards, rules)).equal(false);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test("should hit on soft 17 when hitOnSoft17 is true", () => {
|
|
130
|
+
const cards: Card[] = [];
|
|
131
|
+
cards.push(new Card("Hearts", "A"));
|
|
132
|
+
cards.push(new Card("Diamonds", "6"));
|
|
133
|
+
const rules = BlackjackRules.dealerHitsSoft17();
|
|
134
|
+
expect(dealerShouldHit(cards, rules)).equal(true);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test("should not hit on soft 17 when hitOnSoft17 is false", () => {
|
|
138
|
+
const cards: Card[] = [];
|
|
139
|
+
cards.push(new Card("Hearts", "A"));
|
|
140
|
+
cards.push(new Card("Diamonds", "6"));
|
|
141
|
+
const rules = BlackjackRules.standard();
|
|
142
|
+
expect(dealerShouldHit(cards, rules)).equal(false);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// ============================================================================
|
|
147
|
+
// isSoftHand Tests (from core)
|
|
148
|
+
// ============================================================================
|
|
149
|
+
|
|
150
|
+
describe("isSoftHand (from core)", () => {
|
|
151
|
+
test("should identify soft hand with ace", () => {
|
|
152
|
+
const cards: Card[] = [];
|
|
153
|
+
cards.push(new Card("Hearts", "A"));
|
|
154
|
+
cards.push(new Card("Diamonds", "6"));
|
|
155
|
+
expect(isSoftHand(cards)).equal(true);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test("should identify hard hand without ace", () => {
|
|
159
|
+
const cards: Card[] = [];
|
|
160
|
+
cards.push(new Card("Hearts", "10"));
|
|
161
|
+
cards.push(new Card("Diamonds", "7"));
|
|
162
|
+
expect(isSoftHand(cards)).equal(false);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
test("should identify hard hand with ace used as 1", () => {
|
|
166
|
+
const cards: Card[] = [];
|
|
167
|
+
cards.push(new Card("Hearts", "A"));
|
|
168
|
+
cards.push(new Card("Diamonds", "10"));
|
|
169
|
+
cards.push(new Card("Clubs", "10"));
|
|
170
|
+
expect(isSoftHand(cards)).equal(false);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
test("should identify soft hand with multiple aces", () => {
|
|
174
|
+
const cards: Card[] = [];
|
|
175
|
+
cards.push(new Card("Hearts", "A"));
|
|
176
|
+
cards.push(new Card("Diamonds", "A"));
|
|
177
|
+
cards.push(new Card("Clubs", "5"));
|
|
178
|
+
expect(isSoftHand(cards)).equal(true);
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// ============================================================================
|
|
183
|
+
// calculateBlackjackHandValue Tests (from core)
|
|
184
|
+
// ============================================================================
|
|
185
|
+
|
|
186
|
+
describe("calculateBlackjackHandValue (from core)", () => {
|
|
187
|
+
test("should calculate value for number cards", () => {
|
|
188
|
+
const cards: Card[] = [];
|
|
189
|
+
cards.push(new Card("Hearts", "5"));
|
|
190
|
+
cards.push(new Card("Diamonds", "7"));
|
|
191
|
+
expect(calculateBlackjackHandValue(cards)).equal(12);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
test("should calculate value for face cards", () => {
|
|
195
|
+
const cards: Card[] = [];
|
|
196
|
+
cards.push(new Card("Hearts", "K"));
|
|
197
|
+
cards.push(new Card("Diamonds", "Q"));
|
|
198
|
+
expect(calculateBlackjackHandValue(cards)).equal(20);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
test("should calculate value with ace as 11", () => {
|
|
202
|
+
const cards: Card[] = [];
|
|
203
|
+
cards.push(new Card("Hearts", "A"));
|
|
204
|
+
cards.push(new Card("Diamonds", "6"));
|
|
205
|
+
expect(calculateBlackjackHandValue(cards)).equal(17);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
test("should calculate value with ace as 1 when needed", () => {
|
|
209
|
+
const cards: Card[] = [];
|
|
210
|
+
cards.push(new Card("Hearts", "A"));
|
|
211
|
+
cards.push(new Card("Diamonds", "10"));
|
|
212
|
+
cards.push(new Card("Clubs", "10"));
|
|
213
|
+
expect(calculateBlackjackHandValue(cards)).equal(21);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
test("should calculate blackjack correctly", () => {
|
|
217
|
+
const cards: Card[] = [];
|
|
218
|
+
cards.push(new Card("Hearts", "A"));
|
|
219
|
+
cards.push(new Card("Diamonds", "K"));
|
|
220
|
+
expect(calculateBlackjackHandValue(cards)).equal(21);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
test("should handle multiple aces correctly", () => {
|
|
224
|
+
const cards: Card[] = [];
|
|
225
|
+
cards.push(new Card("Hearts", "A"));
|
|
226
|
+
cards.push(new Card("Diamonds", "A"));
|
|
227
|
+
cards.push(new Card("Clubs", "5"));
|
|
228
|
+
expect(calculateBlackjackHandValue(cards)).equal(17);
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
|