1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
package casino
import (
"fmt"
"testing"
)
func TestRouletteRejectsNonTouchingCombinations(t *testing.T) {
for _, tc := range []struct {
target string
double bool
}{
{"corner 1 3 4 6", false}, {"corner 1 2 7 8", false},
{"corner 1 3 34 36", true}, {"trio 0 1 3", false},
{"trio 0 1 3", true}, {"trio 0 2 3", true},
{"trio 00 1 2", true}, {"trio 0 00 1", true},
{"trio 0 00 3", true}, {"split 0 3", true},
{"split 00 1", true},
} {
if _, mult := rouletteBet(tc.target, tc.double); mult != 0 {
t.Errorf("accepted %q (double=%v)", tc.target, tc.double)
}
}
for _, double := range []bool{false, true} {
for c := 0; c < 11; c++ {
for r := 1; r <= 2; r++ {
n := 3*c + r
target := fmt.Sprintf("corner %d %d %d %d", n, n+1, n+3, n+4)
if _, mult := rouletteBet(target, double); mult != 9 {
t.Errorf("rejected %s", target)
}
}
}
for _, target := range []string{"split 0 1", "split 0 2", "trio 0 1 2"} {
if _, mult := rouletteBet(target, double); mult == 0 {
t.Errorf("rejected %s", target)
}
}
}
for _, target := range []string{"split 00 2", "split 00 3", "trio 00 2 3", "trio 0 00 2"} {
if _, mult := rouletteBet(target, true); mult == 0 {
t.Errorf("rejected %s", target)
}
}
}
// Sum the return over every equally likely outcome. Ordinary bets return
// 36 stakes per wheel; the American five-number basket returns only 35.
func TestRouletteWheelAndExpectedReturns(t *testing.T) {
for _, double := range []bool{false, true} {
wheel := WheelOrder(double)
want := 37
if double {
want = 38
}
seen := map[string]bool{}
for _, p := range wheel {
if _, valid := roulettePocketToken(p, double); !valid || seen[p] {
t.Fatalf("invalid wheel pocket %s", p)
}
seen[p] = true
}
if len(seen) != want {
t.Fatalf("wheel has %d pockets, want %d", len(seen), want)
}
targets := append(WheelOrder(double), "red", "black", "odd", "even", "low", "high", "1to12", "13to24", "25to36", "row1", "row2", "row3", "split 1 2", "street 1 2 3", "corner 1 2 4 5", "line 1 2 3 4 5 6", "trio 0 1 2", "basket")
for _, target := range targets {
wager, ok := rouletteWagerFor(target, double, false)
if !ok {
t.Fatalf("invalid target %s", target)
}
sum := 0
for _, p := range wheel {
share, _ := wager.covers(p)
payout, err := share.payout(1)
if err != nil {
t.Fatal(err)
}
sum += payout
}
wantReturn := 36
if double && target == "basket" {
wantReturn = 35
}
if sum != wantReturn {
t.Errorf("%s: total return %d, want %d", target, sum, wantReturn)
}
}
}
}
func TestRouletteSharePayoutCap(t *testing.T) {
shares := []rouletteShare{{36, 1}, {7, 1}, {36, 9}}
for _, bet := range rouletteCallBets {
for _, share := range bet.wager().shares {
shares = append(shares, share)
}
}
for _, share := range shares {
limit := ((MaxCredits+1)*share.den - 1) / share.num
got, err := share.payout(limit)
if err != nil || got > MaxCredits {
t.Fatalf("%+v at limit: %d, %v", share, got, err)
}
if _, err := share.payout(limit + 1); err == nil {
t.Fatalf("%+v accepted overflow", share)
}
}
}
|